home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianDatasets.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  123KB  |  5,203 lines

  1. /*ScianDatasets.c
  2.   Eric Pepke
  3.   August 17, 1990
  4.   Stuff for Datasets
  5. */
  6.  
  7. #include "Scian.h"
  8. #include "ScianTypes.h"
  9. #include "ScianLists.h"
  10. #include "ScianIcons.h"
  11. #include "ScianWindows.h"
  12. #include "ScianObjWindows.h"
  13. #include "ScianVisWindows.h"
  14. #include "ScianButtons.h"
  15. #include "ScianTextBoxes.h"
  16. #include "ScianControls.h"
  17. #include "ScianDatasets.h"
  18. #include "ScianErrors.h"
  19. #include "ScianColors.h"
  20. #include "ScianDialogs.h"
  21. #include "ScianVisObjects.h"
  22. #include "ScianStyle.h"
  23. #include "ScianSpaces.h"
  24. #include "ScianIDs.h"
  25. #include "ScianArrays.h"
  26. #include "ScianMethods.h"
  27. #include "ScianTimers.h"
  28. #include "ScianDepend.h"
  29. #include "ScianFiles.h"
  30. #include "ScianFileSystem.h"
  31. #include "ScianObjFunctions.h"
  32. #include "ScianSockets.h"
  33. #include "ScianEvents.h"
  34. #include "ScianSciences.h"
  35. #include "ScianGeometry.h"
  36. #include "ScianTemplates.h"
  37. #include "ScianTemplateHelper.h"
  38. #include "ScianDatabase.h"
  39. #include "ScianSymbols.h"
  40. #include "ScianFontSystem.h"
  41.  
  42. #define VISMENU
  43. #define SHOWCTLMENU
  44.  
  45. ObjPtr geometryClass;            /*Class for geometry object*/
  46. ObjPtr datasetClass, data3DScalar, data2DScalar, data1DVector, data3DUnstructSurface;
  47. ObjPtr iconDataset;
  48. ObjPtr icon1DVector, icon2DVector, icon3DVector, icon4DVector;
  49. ObjPtr icon1DScalar, icon2DScalar, icon3DScalar, icon4DScalar;
  50. ObjPtr iconGeometry;
  51. ObjPtr globalDataset;
  52. Bool timedDatasets = true;        /*True iff reading timed datasets*/
  53. ObjPtr dataFormClass;
  54. static ObjPtr dsLocArray = NULLOBJ;    /*Location of icon for dataset*/
  55.  
  56. Bool onePalette = false;
  57. ObjPtr commonPalette;
  58.  
  59. /*Current fields.  Double, because there might be time dependence*/
  60. DatasetBuffer curFields[MAXNCURFIELDS * 2];
  61.  
  62. #ifdef PROTO
  63. ObjPtr NewGeometryDataset(char *name)
  64. #else
  65. ObjPtr NewGeometryDataset(name)
  66. char *name;
  67. #endif
  68. {
  69.     ObjPtr retVal;
  70.     retVal = NewObject(datasetClass, 0L);
  71.     SetVar(retVal, DEFAULTICON, iconGeometry);
  72.     SetVar(retVal, NAME, NewString(name));
  73.  
  74.     return retVal;
  75. }
  76.  
  77. #ifdef PROTO
  78. ObjPtr NewDataset(char *name, int rank, long *dims, int nComponents)
  79. #else
  80. ObjPtr NewDataset(name, rank, dims, nComponents)
  81. char *name;
  82. int rank;
  83. long *dims;
  84. int nComponents;
  85. #endif
  86. /*Makes a new dataset
  87.   name        is the name of the dataset
  88.   rank        is the rank of the dataset
  89.   dims        is a pointer to the dimensions
  90.   nComponents    is the number of components, 0 for scalar
  91. */
  92. {
  93.     ObjPtr retVal;
  94.     ObjPtr dimensions;
  95.     real *elements;
  96.     ObjPtr data;
  97.     int k;
  98.  
  99.     /*Make the dataset*/
  100.     retVal = NewObject(datasetClass, 0L);
  101.  
  102.     /*Make its dimensions*/
  103.     if (rank)
  104.     {
  105.     dimensions = NewRealArray(1, (long) rank);
  106.     elements = ELEMENTS(dimensions);
  107.     for (k = 0; k < rank; ++k)
  108.     {
  109.         elements[k] = (real) dims[k];
  110.     }
  111.     SetVar(retVal, DIMENSIONS, dimensions);
  112.     }
  113.  
  114.     /*Set its NCOMPONENTS*/
  115.     if (nComponents)
  116.     {
  117.     SetVar(retVal, NCOMPONENTS, NewInt(nComponents));
  118.     }
  119.  
  120.     /*Set its NAME*/
  121.     SetVar(retVal, NAME, NewString(name));
  122.  
  123.     /*Set its DATA*/
  124.     if (nComponents)
  125.     {
  126.     ObjPtr *objectElements;
  127.     long dummy;
  128.  
  129.     /*Vector data*/
  130.     dummy = nComponents;
  131.     data = NewArray(AT_OBJECT, 1, &dummy);
  132.  
  133.     objectElements = (ObjPtr *) ELEMENTS(data);
  134.  
  135.     for (k = 0; k < nComponents; ++k)
  136.     {
  137.         objectElements[k] = NewArray(AT_REAL, rank, dims);
  138.     }
  139.     }
  140.     else
  141.     {
  142.     /*Scalar data*/
  143.     data = NewArray(AT_REAL, rank, dims);
  144.     }
  145.     SetVar(retVal, DATA, data);
  146.  
  147.     /*Set its DEFAULTICON*/
  148.     if (nComponents)
  149.     {
  150.     /*Vector*/
  151.     switch (rank)
  152.     {
  153.         case 0:    /*DIKEO Really should have a value, here*/
  154.         case 1:     SetVar(retVal, DEFAULTICON, icon1DVector); break;
  155.         case 2:     SetVar(retVal, DEFAULTICON, icon2DVector); break;
  156.         case 3:     SetVar(retVal, DEFAULTICON, icon3DVector); break;
  157.         default:    SetVar(retVal, DEFAULTICON, icon4DVector); break;
  158.     }
  159.     }
  160.     else
  161.     {
  162.     /*Scalar*/
  163.     switch (rank)
  164.     {
  165.         case 0:    /*DIKEO Really should have a value, here*/
  166.         case 1:     SetVar(retVal, DEFAULTICON, icon1DScalar); break;
  167.         case 2:     SetVar(retVal, DEFAULTICON, icon2DScalar); break;
  168.         case 3:     SetVar(retVal, DEFAULTICON, icon3DScalar); break;
  169.         default:    SetVar(retVal, DEFAULTICON, icon4DScalar); break;
  170.     }
  171.     }
  172.  
  173.     return retVal;
  174. }
  175.  
  176. #ifdef PROTO
  177. ObjPtr NewCompressedDataset(char *name, int rank, long *dims, int nComponents, real cTable[256])
  178. #else
  179. ObjPtr NewCompressedDataset(name, rank, dims, nComponents, cTable)
  180. char *name;
  181. int rank;
  182. long *dims;
  183. int nComponents;
  184. real cTable[256];
  185. #endif
  186. /*Makes a new compressed dataset
  187.   name        is the name of the dataset
  188.   rank        is the rank of the dataset
  189.   dims        is a pointer to the dimensions
  190.   nComponents    is the number of components, 0 for scalar
  191.   cTable    is the compression table
  192. */
  193. {
  194.     ObjPtr retVal;
  195.     ObjPtr dimensions;
  196.     real *elements;
  197.     ObjPtr data;
  198.     int k;
  199.     ObjPtr cTableVar;
  200.  
  201.     /*Make the dataset*/
  202.     retVal = NewObject(datasetClass, 0L);
  203.  
  204.     /*Make its dimensions*/
  205.     if (rank)
  206.     {
  207.     dimensions = NewRealArray(1, (long) rank);
  208.     elements = ELEMENTS(dimensions);
  209.     for (k = 0; k < rank; ++k)
  210.     {
  211.         elements[k] = (real) dims[k];
  212.     }
  213.     SetVar(retVal, DIMENSIONS, dimensions);
  214.     }
  215.  
  216.     /*Set its NCOMPONENTS*/
  217.     if (nComponents)
  218.     {
  219.     SetVar(retVal, NCOMPONENTS, NewInt(nComponents));
  220.     }
  221.  
  222.     /*Set its NAME*/
  223.     SetVar(retVal, NAME, NewString(name));
  224.  
  225.     /*Make the compression table*/
  226.     cTableVar = NewRealArray(1, 256L);
  227.     if (!cTableVar)
  228.     {
  229.     OMErr();
  230.     return NULLOBJ;
  231.     }
  232.     CArray2Array(cTableVar, cTable);
  233.  
  234.     /*Set its DATA*/
  235.     if (nComponents)
  236.     {
  237.     ObjPtr *objectElements;
  238.     long dummy;
  239.  
  240.     /*Vector data*/
  241.     dummy = nComponents;
  242.     data = NewArray(AT_OBJECT, 1, &dummy);
  243.  
  244.     objectElements = (ObjPtr *) ELEMENTS(data);
  245.  
  246.     for (k = 0; k < nComponents; ++k)
  247.     {
  248.         objectElements[k] = NewArray(AT_BYTE, rank, dims);
  249.         SetVar(objectElements[k], CTABLE, cTableVar);
  250.     }
  251.     }
  252.     else
  253.     {
  254.     /*Scalar data*/
  255.     data = NewArray(AT_BYTE, rank, dims);
  256.     SetVar(data, CTABLE, cTableVar);
  257.     }
  258.     SetVar(retVal, DATA, data);
  259.  
  260.     /*Set its DEFAULTICON*/
  261.     if (nComponents)
  262.     {
  263.     /*Vector*/
  264.     switch (rank)
  265.     {
  266.         case 0:    /*DIKEO Really should have a value, here*/
  267.         case 1:     SetVar(retVal, DEFAULTICON, icon1DVector); break;
  268.         case 2:     SetVar(retVal, DEFAULTICON, icon2DVector); break;
  269.         case 3:     SetVar(retVal, DEFAULTICON, icon3DVector); break;
  270.         default:    SetVar(retVal, DEFAULTICON, icon4DVector); break;
  271.     }
  272.     }
  273.     else
  274.     {
  275.     /*Scalar*/
  276.     switch (rank)
  277.     {
  278.         case 0:    /*DIKEO Really should have a value, here*/
  279.         case 1:     SetVar(retVal, DEFAULTICON, icon1DScalar); break;
  280.         case 2:     SetVar(retVal, DEFAULTICON, icon2DScalar); break;
  281.         case 3:     SetVar(retVal, DEFAULTICON, icon3DScalar); break;
  282.         default:    SetVar(retVal, DEFAULTICON, icon4DScalar); break;
  283.     }
  284.     }
  285.  
  286.     return retVal;
  287. }
  288.  
  289. #ifdef PROTO
  290. ObjPtr NewSeparableDataForm(char *name, int rank, long *dims, real *scales[])
  291. #else
  292. ObjPtr NewSeparableDataForm(name, rank, dims, scales)
  293. char *name;
  294. int rank;
  295. long *dims;
  296. real *scales[];
  297. #endif
  298. /*Makes a new rectilinear data form with separable axes
  299.   name        is the name of the dataset
  300.   rank        is the rank of the dataset
  301.   dims        is a pointer to the dimensions
  302.   scales    is an array, rank rank, containing elements of size
  303.         dims[k] giving scale along that axis
  304. */
  305. {
  306.     ObjPtr retVal;
  307.     ObjPtr dimensions;
  308.     ObjPtr bounds;
  309.     real *elements;
  310.     ObjPtr *objElements;
  311.     ObjPtr data, axes;
  312.     int k;
  313.     long temp;
  314.  
  315.     /*Create the data form*/
  316.     retVal = NewObject(dataFormClass, 0L);
  317.  
  318.     /*Make its dimensions*/
  319.     dimensions = NewRealArray(1, (long) rank);
  320.     elements = ELEMENTS(dimensions);
  321.     for (k = 0; k < rank; ++k)
  322.     {
  323.     elements[k] = (real) dims[k];
  324.     }
  325.     SetVar(retVal, DIMENSIONS, dimensions);
  326.  
  327.     /*Set its NAME*/
  328.     SetVar(retVal, NAME, NewString(name));
  329.  
  330.     /*Make its BOUNDS*/
  331.     bounds = NewRealArray(1, 2L * (long) rank);
  332.     if (!bounds)
  333.     {
  334.     return NULLOBJ;
  335.     }
  336.     elements = ELEMENTS(bounds);
  337.     for (k = 0; k < rank; ++k)
  338.     {
  339.     int i;
  340.     real min, max;
  341.  
  342.     min = max = scales[k][0];
  343.     for (i = 1; i < dims[k]; ++i)
  344.     {
  345.         if (scales[k][i] < min) min = scales[k][i];
  346.         if (scales[k][i] > max) max = scales[k][i];
  347.     }
  348.     elements[k * 2] = min;
  349.     elements[k * 2 + 1] = max;
  350.     }
  351.     SetVar(retVal, BOUNDS, bounds);
  352.  
  353.     /*Now make a dataset which specifies the field*/
  354.     data = NewObject(datasetClass, 0);
  355.     if (!data)
  356.     {
  357.     return NULLOBJ;
  358.     }
  359.  
  360.     /*Set its NAME*/
  361.     SetVar(data, NAME, NewString(name));
  362.  
  363.     /*Set its NCOMPONENTS*/
  364.     SetVar(data, NCOMPONENTS, NewInt(rank));
  365.  
  366.     /*Make an array of axes for the data*/
  367.     temp = rank;
  368.     axes = NewArray(AT_OBJECT, 1, &temp);
  369.     if (!axes)
  370.     {
  371.     return NULLOBJ;
  372.     }
  373.     SetVar(data, DATA, axes);
  374.  
  375.     /*Fill the axes*/
  376.     objElements = ELEMENTS(axes);
  377.     for (k = 0; k < rank; ++k)
  378.     {
  379.     ObjPtr indices, scaleArray;
  380.     long i;
  381.  
  382.     /*Copy over the scale*/
  383.     scaleArray = NewRealArray(1, dims[k]);
  384.     elements = ELEMENTS(scaleArray);
  385.     objElements[k] = scaleArray;
  386.  
  387.     for (i = 0; i < dims[k]; ++i)
  388.     {
  389.         elements[i] = scales[k][i];
  390.     }
  391.     
  392.     /*Give it an INDICES array*/
  393.     indices = NewRealArray(1, 1L);
  394.     *(real *)ELEMENTS(indices) = k;
  395.     SetVar(objElements[k], INDICES, indices);
  396.     }
  397.     SetVar(retVal, DATA, data);
  398.  
  399.     return retVal;
  400. }
  401.  
  402. #ifdef PROTO
  403. ObjPtr NewUnstructuredDataForm(char *name, int rank, long *dims, real *bounds, ObjPtr dataset)
  404. #else
  405. ObjPtr NewUnstructuredDataForm(name, rank, dims, bounds, dataset)
  406. char *name;
  407. int rank;
  408. long *dims;
  409. real *bounds;
  410. ObjPtr dataset;
  411. #endif
  412. /*Makes a new unstructured data form
  413.   name        is the name of the data form
  414.   rank        is the rank of the dataset
  415.         0 = just nodes
  416.         1 = + links
  417.         2 = + faces
  418.         3 = + cells, etc.
  419.   dims        is a pointer to the dimensions
  420.         This must be one greater than rank
  421.         0 = number of nodes, 1 = number of links, etc.
  422.   bounds    is the bounds of the dataform, rank # components of dataform
  423.   dataset    is the dataset that is used for the data form
  424. */
  425. {
  426.     ObjPtr retVal;
  427.     ObjPtr dimensions;
  428.     ObjPtr boundsArray;
  429.     real *elements;
  430.     ObjPtr *objElements;
  431.     ObjPtr data, axes;
  432.     ObjPtr var;
  433.     int nComponents;
  434.     int k;
  435.     long temp;
  436.  
  437.     /*Create the data form*/
  438.     retVal = NewObject(dataFormClass, 0L);
  439.     SetVar(retVal, UNSTRUCTURED, ObjTrue);
  440.  
  441.     /*Make its dimensions*/
  442.     dimensions = NewRealArray(1, (long) rank + 1);
  443.     elements = ELEMENTS(dimensions);
  444.     for (k = 0; k < rank + 1; ++k)
  445.     {
  446.     elements[k] = (real) dims[k];
  447.     }
  448.     SetVar(retVal, DIMENSIONS, dimensions);
  449.  
  450.     /*Set its NAME*/
  451.     SetVar(retVal, NAME, NewString(name));
  452.  
  453.     if (rank > 0 && dims[1])
  454.     {
  455.     real *elements;
  456.  
  457.     var = NewRealArray(2, dims[1], 2L);
  458.     elements = ELEMENTS(var);
  459.     for (k = 0; k < dims[1] * 2; ++k)
  460.     {
  461.         elements[k] = -1.0;
  462.     }
  463.     SetVar(retVal, EDGES, var);
  464.     }
  465.  
  466.     /*Calculate its BOUNDS*/
  467.     var = GetIntVar("NewUnstructuredDataForm", dataset, NCOMPONENTS);
  468.     if (var)
  469.     {
  470.     nComponents = GetInt(var);
  471.     }
  472.     else
  473.     {
  474.     return NULLOBJ;
  475.     }
  476.     SetVar(retVal, NCOMPONENTS, NewInt(nComponents));
  477.     boundsArray = NewRealArray(1, 2L * (long) nComponents);
  478.     if (!boundsArray)
  479.     {
  480.     return NULLOBJ;
  481.     }
  482.     elements = ELEMENTS(boundsArray);
  483.     for (k = 0; k < nComponents; ++k)
  484.     {
  485.     elements[k * 2] = bounds[k * 2];
  486.     elements[k * 2 + 1] = bounds[k * 2 + 1];
  487.     }
  488.     SetVar(retVal, BOUNDS, boundsArray);
  489.  
  490.     SetVar(retVal, DATA, dataset);
  491.  
  492.     return retVal;
  493. }
  494.  
  495. #ifdef PROTO
  496. void Put1Edge(ObjPtr dataForm, long edge, long v1, long v2)
  497. #else
  498. void Put1Edge(ObjPtr dataForm, long edge, long v1, long v2)
  499. #endif
  500. /*Puts a 1-edge numbered edge into dataForm from v1 to v2*/
  501. {
  502.     ObjPtr var;
  503.     var = GetVar(dataForm, EDGES);
  504.     if (var)
  505.     {
  506.     TwoReals *elements;
  507.     elements = (TwoReals *) ELEMENTS(var);
  508.     elements[edge][0] = (real) v1;
  509.     elements[edge][1] = (real) v2;
  510.     }
  511. }
  512.  
  513. #ifdef PROTO
  514. void AppendPolygonToDataset(ObjPtr dataset, long nVertices, long vertices[])
  515. #else
  516. void AppendPolygonToDataset(dataset, nVertices, vertices)
  517. ObjPtr dataForm;
  518. long nVertices;
  519. long vertices;
  520. #endif
  521. /*Appends an indexed polygon to a data set*/
  522. {
  523.     ObjPtr geometry;
  524.  
  525.     geometry = GetVar(dataset, DATA);
  526.     if (!geometry)
  527.     {
  528.     geometry = NewGeometry();
  529.     SetVar(dataset, DATA, geometry);
  530.     }
  531.     AppendPolygonToGeometry(geometry, nVertices, vertices);
  532. }
  533.  
  534. #ifdef PROTO
  535. ObjPtr NewRegularDataForm(char *name, int rank, long *dims, real *bounds)
  536. #else
  537. ObjPtr NewRegularDataForm(name, rank, dims, bounds)
  538. char *name;
  539. int rank;
  540. long *dims;
  541. real *bounds;
  542. #endif
  543. /*Makes a new regulat data form
  544.   name        is the name of the dataset
  545.   rank        is the rank of the dataset
  546.   dims        is a pointer to the dimensions
  547.   bounds    is the bounds of the dataform, rank 1, size 2 * rank
  548. */
  549. {
  550.     ObjPtr retVal;
  551.     ObjPtr dimensions;
  552.     ObjPtr boundsArray;
  553.     real *elements;
  554.     ObjPtr *objElements;
  555.     ObjPtr data, axes;
  556.     int k;
  557.     long temp;
  558.  
  559.     /*Create the data form*/
  560.     retVal = NewObject(dataFormClass, 0L);
  561.  
  562.     /*Make its dimensions*/
  563.     dimensions = NewRealArray(1, (long) rank);
  564.     elements = ELEMENTS(dimensions);
  565.     for (k = 0; k < rank; ++k)
  566.     {
  567.     elements[k] = (real) dims[k];
  568.     }
  569.     SetVar(retVal, DIMENSIONS, dimensions);
  570.  
  571.     /*Set its NAME*/
  572.     SetVar(retVal, NAME, NewString(name));
  573.  
  574.     /*Make its BOUNDS*/
  575.     boundsArray = NewRealArray(1, 2L * (long) rank);
  576.     if (!boundsArray)
  577.     {
  578.     return NULLOBJ;
  579.     }
  580.     elements = ELEMENTS(boundsArray);
  581.     for (k = 0; k < rank; ++k)
  582.     {
  583.     elements[k * 2] = bounds[k * 2];
  584.     elements[k * 2 + 1] = bounds[k * 2 + 1];
  585.     }
  586.     SetVar(retVal, BOUNDS, boundsArray);
  587.  
  588.     return retVal;
  589. }
  590.  
  591. #ifdef PROTO
  592. ObjPtr NewCurvilinearDataForm(char *name, int rank, long *dims, real *bounds, ObjPtr dataset)
  593. #else
  594. ObjPtr NewCurvilinearDataForm(name, rank, dims, bounds, dataset)
  595. char *name;
  596. int rank;
  597. long *dims;
  598. real *bounds;
  599. ObjPtr dataset;
  600. #endif
  601. /*Makes a new curvilinear data
  602.   name        is the name of the data form
  603.   rank        is the rank of the data form
  604.   dims        is a pointer to the dimensions
  605.   bounds    is the bounds of the dataform, rank # components of dataform
  606.   dataset    is the dataset that is used for the data form
  607. */
  608. {
  609.     ObjPtr retVal;
  610.     ObjPtr dimensions;
  611.     ObjPtr boundsArray;
  612.     real *elements;
  613.     ObjPtr *objElements;
  614.     ObjPtr data, axes;
  615.     ObjPtr var;
  616.     int nComponents;
  617.     int k;
  618.     long temp;
  619.  
  620.     /*Create the data form*/
  621.     retVal = NewObject(dataFormClass, 0L);
  622.  
  623.     /*Make its dimensions*/
  624.     dimensions = NewRealArray(1, (long) rank);
  625.     elements = ELEMENTS(dimensions);
  626.     for (k = 0; k < rank; ++k)
  627.     {
  628.     elements[k] = (real) dims[k];
  629.     }
  630.     SetVar(retVal, DIMENSIONS, dimensions);
  631.  
  632.     /*Set its NAME*/
  633.     SetVar(retVal, NAME, NewString(name));
  634.  
  635.     /*Calculate its BOUNDS*/
  636.     var = GetIntVar("NewCurvilinearDataForm", dataset, NCOMPONENTS);
  637.     if (var)
  638.     {
  639.     nComponents = GetInt(var);
  640.     }
  641.     else
  642.     {
  643.     return NULLOBJ;
  644.     }
  645.     SetVar(retVal, NCOMPONENTS, NewInt(nComponents));
  646.     boundsArray = NewRealArray(1, 2L * (long) nComponents);
  647.     if (!boundsArray)
  648.     {
  649.     return NULLOBJ;
  650.     }
  651.     elements = ELEMENTS(boundsArray);
  652.     for (k = 0; k < nComponents; ++k)
  653.     {
  654.     elements[k * 2] = bounds[k * 2];
  655.     elements[k * 2 + 1] = bounds[k * 2 + 1];
  656.     }
  657.     SetVar(retVal, BOUNDS, boundsArray);
  658.  
  659.     SetVar(retVal, DATA, dataset);
  660.  
  661.     return retVal;
  662. }
  663.  
  664. #ifdef PROTO
  665. void SetDatasetPalette(ObjPtr dataset, ObjPtr palette)
  666. #else
  667. void SetDatasetPalette(dataset, palette)
  668. ObjPtr dataset, palette;
  669. #endif
  670. /*Sets a dataset's palette*/
  671. {
  672.     FieldPaletteName(palette, dataset);
  673.     SetVar(dataset, CPALETTE, palette);
  674. }
  675.  
  676. #ifdef PROTO
  677. void SetDatasetForm(ObjPtr dataset, ObjPtr dataForm)
  678. #else
  679. void SetDatasetForm(dataset, dataForm)
  680. ObjPtr dataset, dataForm;
  681. /*Sets a dataset's data form*/
  682. #endif
  683. {
  684.     SetVar(dataset, DATAFORM, dataForm);
  685. }
  686.  
  687. ObjPtr GetLongName(dataset)
  688. ObjPtr dataset;
  689. /*Gets the long name of dataset*/
  690. {
  691.     FuncTyp method;
  692.     method = GetMethod(dataset, GETLONGNAME);
  693.     if (method)
  694.     {
  695.     return (*method)(dataset);
  696.     }
  697.     else
  698.     {
  699.     return NULLOBJ;
  700.     }
  701. }
  702.  
  703. ObjPtr GetPlainDatasetLongName(dataset)
  704. ObjPtr dataset;
  705. /*Gets the long name of a plain dataset*/
  706. {
  707.     return GetVar(dataset, NAME);
  708. }
  709.  
  710. #ifdef PROTO
  711. static DeleteBuckets(int whichField)
  712. #else
  713. static DeleteBuckets(whichField)
  714. int whichField;
  715. #endif
  716. /*Deletes the buckets from within a field*/
  717. {
  718.     if (curFields[whichField] . bucketMinMax)
  719.     {
  720.     /*It has buckets, get rid of them*/
  721.     long k;
  722.     long nBuckets;
  723.  
  724.     /*Figure out how many buckets there are*/
  725.     nBuckets = 1;
  726.     for (k = 0; k < curFields[whichField] . nBucketIndices; ++k)
  727.     {
  728.         if (curFields[whichField] . bucketDim[k])
  729.         {
  730.         nBuckets += curFields[whichField] . bucketDim[k];
  731.         }
  732.     }
  733.  
  734.     /*Empty the buckets*/
  735.     for (k = 0; k < nBuckets; ++k)
  736.     {
  737.         if (curFields[whichField] . buckets[k] . indices)
  738.         {
  739.         Free(curFields[whichField] . buckets[k] . indices);
  740.         }
  741.         if (curFields[whichField] . buckets[k] . samples)
  742.         {
  743.         Free(curFields[whichField] . buckets[k] . samples);
  744.         }
  745.     }
  746.     Free(curFields[whichField] . buckets);
  747.     curFields[whichField] . buckets = 0;
  748.  
  749.     /*Get rid of the min and max*/
  750.     Free(curFields[whichField] . bucketMinMax);
  751.     curFields[whichField] . bucketMinMax = 0;
  752.  
  753.     /*Get rid of the dimensions*/
  754.     Free(curFields[whichField] . bucketDim);
  755.     curFields[whichField] . bucketDim = 0;
  756.     }
  757. }
  758.  
  759. #ifdef PROTO
  760. static void CleanCurField(int k)
  761. #else
  762. static void CleanCurField(k)
  763. int k;
  764. #endif
  765. /*Cleans the current field number k*/
  766. {
  767.     DeleteBuckets(k);
  768.     if (curFields[k] . components)
  769.     {
  770.     int i;
  771.     for (i = 0; i < curFields[k] . nComponents; ++i)
  772.     {
  773.         SAFEFREE(curFields[k] . components[i] . indices);
  774.         SAFEFREE(curFields[k] . components[i] . dimensions);
  775.         SAFEFREE(curFields[k] . components[i] . steps);
  776.     }
  777.     SAFEFREE(curFields[k] . components);
  778.     }
  779.     curFields[k] . nComponents = 0;
  780.     curFields[k] . components = (Component *) 0;
  781.     curFields[k] . substMissing = false;
  782.     curFields[k] . missingVal = 0.0;
  783.     curFields[k] . groupInterp = false;
  784.     curFields[k] . weight = 1.0;
  785.     curFields[k] . objectInfo = NULLOBJ;
  786. }
  787.  
  788. ObjPtr MakeDatasetTimesteps(dataset)
  789. ObjPtr dataset;
  790. /*Makes the dataset's TIMESTEPS.  Returns ObjTrue if it had to make it*/
  791. {
  792.     ObjPtr data = NULLOBJ, timesteps = NULLOBJ;
  793.  
  794.     data = GetVar(dataset, DATA);
  795.     if (data)
  796.     {
  797.     MakeVar(data, TIMESTEPS);
  798.     timesteps = GetVar(data, TIMESTEPS);
  799.     }
  800.     else
  801.     {
  802.     SetVar(dataset, TIMESTEPS, NULLOBJ);
  803.     return ObjTrue;
  804.     }
  805.     SetVar(dataset, TIMESTEPS, timesteps);
  806.     return ObjTrue;
  807. }
  808.  
  809.  
  810. #ifdef PROTO
  811. Bool SampleSpatComponent(int dataField, int formField,
  812.     int nResultComp, real resultComp[], int nSpatIndices, 
  813.     real spatIndices[], Bool interpolate)
  814. #else
  815. Bool SampleSpatComponent(dataField, formField, nResultComp, resultComp, nSpatIndices, spatIndices, interpolate)
  816. int dataField, formField;
  817. int nResultComp;
  818. real resultComp[];
  819. int nSpatIndices;
  820. real spatIndices[];
  821. Bool interpolate;
  822. #endif
  823. /*Samples a field dataField defined over formField using nSpatIndices spatIndices and puts
  824.   the result in resultComp components*/
  825. {
  826.     long *topIndices;
  827.     real *rTopIndices;
  828.     long indexBuffer[10];
  829.     real rIndexBuffer[10];
  830.     int nTopIndices;
  831.     int k;
  832.  
  833.     nTopIndices = curFields[formField] . topDim;
  834.     if (nTopIndices != curFields[dataField] . topDim)
  835.     {
  836.     ReportError("SampleSpatComponent", "Topological dimension mismatch");
  837.     return false;
  838.     }
  839.  
  840.     if (nResultComp != curFields[dataField] . nComponents)
  841.     {
  842.     ReportError("SampleSpatComponent", "Wrong number of result components");
  843.     return false;
  844.     }
  845.  
  846.     if (nTopIndices <= 10)
  847.     {
  848.     topIndices = &(indexBuffer[0]);
  849.     rTopIndices = &(rIndexBuffer[0]);
  850.     }
  851.     else
  852.     {
  853.     topIndices = Alloc(nTopIndices * sizeof(long));
  854.     rTopIndices = Alloc(nTopIndices * sizeof(real));
  855.     }
  856.     SampleToTopIndex(formField, nTopIndices, rTopIndices, nSpatIndices, spatIndices);
  857.     for (k = 0; k < nTopIndices; ++k)
  858.     {
  859.     topIndices[k] = rTopIndices[k] + 0.5;
  860.     }
  861.  
  862.     for (k = 0; k < nResultComp; ++k)
  863.     {
  864.     if (interpolate)
  865.     {
  866.         resultComp[k] = InterpolateFieldComponent(dataField, k, rTopIndices);
  867.     }
  868.     else
  869.     {
  870.         resultComp[k] = SelectFieldComponent(dataField, k, topIndices);
  871.     }
  872.     }
  873.  
  874.     if (nTopIndices > 10)
  875.     {
  876.     Free(topIndices);
  877.     Free(rTopIndices);
  878.     }
  879.  
  880.     return true;
  881. }
  882.  
  883. #ifdef PROTO
  884. real SampleSpatScalar(int dataField, int formField,
  885.     int nSpatIndices, 
  886.     real spatIndices[], Bool interpolate)
  887. #else
  888. real SampleSpatScalar(dataField, formField, nSpatIndices, spatIndices, interpolate)
  889. int dataField, formField;
  890. int nSpatIndices;
  891. real spatIndices[];
  892. Bool interpolate;
  893. #endif
  894. /*Samples a scalar field dataField defined over formField using nSpatIndices
  895.   spatIndices and returns the result
  896. */
  897. {
  898.     real retVal;
  899.     long *topIndices;
  900.     real *rTopIndices;
  901.     long indexBuffer[10];
  902.     real rIndexBuffer[10];
  903.     int nTopIndices;
  904.     int k;
  905.  
  906.     nTopIndices = curFields[formField] . topDim;
  907.     if (nTopIndices != curFields[dataField] . topDim)
  908.     {
  909.     ReportError("SampleSpatScalar", "Topological dimension mismatch");
  910.     return false;
  911.     }
  912.  
  913.     if (nTopIndices <= 10)
  914.     {
  915.     topIndices = &(indexBuffer[0]);
  916.     rTopIndices = &(rIndexBuffer[0]);
  917.     }
  918.     else
  919.     {
  920.     topIndices = Alloc(nTopIndices * sizeof(long));
  921.     rTopIndices = Alloc(nTopIndices * sizeof(real));
  922.     }
  923.     SampleToTopIndex(formField, nTopIndices, rTopIndices, nSpatIndices, spatIndices);
  924.     for (k = 0; k < nTopIndices; ++k)
  925.     {
  926.     topIndices[k] = rTopIndices[k] + 0.5;
  927.     }
  928.  
  929.  
  930.     if (interpolate)
  931.     {
  932.         retVal = InterpolateFieldScalar(dataField, rTopIndices);
  933.     }
  934.     else
  935.     {
  936.         retVal = SelectFieldScalar(dataField, topIndices);
  937.     }
  938.  
  939.     if (nTopIndices > 10)
  940.     {
  941.     Free(topIndices);
  942.     Free(rTopIndices);
  943.     }
  944.  
  945.     return retVal;
  946. }
  947.  
  948. #ifdef PROTO
  949. void CalcBucketIndices(long indices[], int whichField, int nSamples, real *samples)
  950. #else
  951. void CalcBucketIndices(indices, whichField, nSamples, samples)
  952. long indices[];
  953. int whichField;
  954. int nSamples;
  955. real *samples;
  956. #endif
  957. /*Calculates the bucket indices of samples within whichField.  Indices
  958.   must be an array of size == number of components in whichField*/
  959. {
  960.     long k;
  961.     real div;
  962.  
  963.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  964.     {
  965.     if (k >= nSamples)
  966.     {
  967.         /*Higher dimensionality, don't change offset*/
  968.         indices[k] = 0;
  969.     }    
  970.     else if (samples[k] < curFields[whichField] . bucketMinMax[k][0])
  971.     {
  972.         /*Less than min, it's just zero.*/
  973.         indices[k] = 0;
  974.     }
  975.     else
  976.     {
  977.         long i;
  978.  
  979.         /*Calculate one of the divisions*/
  980.         div =  (curFields[whichField] . bucketMinMax[k][1] -
  981.             curFields[whichField] . bucketMinMax[k][0]) /
  982.             curFields[whichField] . bucketDim[k];
  983.         i = (samples[k] - curFields[whichField] . bucketMinMax[k][0]) / div;
  984.         if (i >= curFields[whichField] . bucketDim[k])
  985.         {
  986.         i = curFields[whichField] . bucketDim[k] - 1;
  987.         }
  988.         indices[k] = i;
  989.     }
  990.     }
  991. }
  992.  
  993. #ifdef PROTO
  994. long CalcBucketOffset(int whichField, long indices[])
  995. #else
  996. long CalcBucketOffset(whichField, indices)
  997. int whichField;
  998. long indices[]
  999. #endif
  1000. /*Calculates the bucket offset from indices within whichField*/
  1001. {
  1002.     long k;
  1003.     real div;
  1004.     long offset;
  1005.  
  1006.     offset = 0;
  1007.  
  1008.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  1009.     {
  1010.     if (k > 0)
  1011.     {
  1012.         offset *= curFields[whichField] . bucketDim[k - 1];
  1013.     }
  1014.     offset += indices[k];
  1015.     }
  1016.  
  1017.     return offset;
  1018. }
  1019.  
  1020. #ifdef PROTO
  1021. static void FillBuckets(int whichField, int whichIndex, int maxNIndices, long *dimensions, long *indices)
  1022. #else
  1023. static void FillBuckets(whichField, whichIndex, maxNIndices, dimensions, indices)
  1024. int whichField;
  1025. int whichIndex;
  1026. int maxNIndices;
  1027. long *dimensions;
  1028. long *indices;
  1029. #endif
  1030. /*Fills the buckets of whichField using a
  1031.   powerset technique over indices.  Stuffs them into min and max*/
  1032. {
  1033.     if (whichIndex >= maxNIndices)
  1034.     {
  1035.     /*Bottomed out.  Spit out the sample*/
  1036.     long offset;
  1037.     long i, k;
  1038.     real *samples;
  1039.     long *bucketIndices;
  1040.     register Bucket *bucket;
  1041.  
  1042.     /*Calculate the offset*/
  1043.     samples = (real *) Alloc(curFields[whichField] . nComponents * sizeof(real));
  1044.     bucketIndices = (long *) Alloc(curFields[whichField] . nComponents * sizeof(long));
  1045.  
  1046.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  1047.     {
  1048.         samples[k] = SelectFieldComponent(whichField, k, indices);
  1049.     }
  1050.     CalcBucketIndices(bucketIndices, whichField,
  1051.             curFields[whichField] . nComponents,
  1052.             samples);
  1053.     offset = CalcBucketOffset(whichField, bucketIndices);
  1054.  
  1055.     /*OK, got the offset.  Look at the bucket.*/
  1056.     bucket = &(curFields[whichField] . buckets[offset]);
  1057.  
  1058.     /*Go to the next slot on the bucket*/
  1059.     if (0 == (bucket -> nIndices % ADDBUCKETS))
  1060.     {
  1061.         /*Must allocate some new buckets*/
  1062.         if (bucket -> nIndices)
  1063.         {
  1064.         bucket -> indices = (long *) Realloc(bucket -> indices,
  1065.             (ADDBUCKETS + bucket -> nIndices) *
  1066.             sizeof(long) * maxNIndices);
  1067.         bucket -> samples = (real *) Realloc(bucket -> samples,
  1068.             (ADDBUCKETS + bucket -> nIndices) *
  1069.             sizeof(real) * curFields[whichField] . nComponents);
  1070.         }
  1071.         else
  1072.         {
  1073.         bucket -> indices = (long *) Alloc(
  1074.             ADDBUCKETS *
  1075.             sizeof(long) * maxNIndices);
  1076.         bucket -> samples = (real *) Alloc(
  1077.             ADDBUCKETS *
  1078.             sizeof(real) * curFields[whichField] . nComponents);
  1079.         }
  1080.     }
  1081.  
  1082.     /*Insert this series of indices, and the sample*/
  1083.     i = bucket -> nIndices * maxNIndices;
  1084.     for (k = 0; k < maxNIndices; ++k)
  1085.     {
  1086.         bucket -> indices[i] = indices[k];
  1087.         ++i;
  1088.     }
  1089.     i = bucket -> nIndices * curFields[whichField] . nComponents;
  1090.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  1091.     {
  1092.         bucket -> samples[i] = samples[k];
  1093.         ++i;
  1094.     }
  1095.  
  1096.     /*Advance pointer*/
  1097.     ++(bucket -> nIndices);
  1098.  
  1099.     /*No more samples needed*/
  1100.     Free(bucketIndices);
  1101.     Free(samples);
  1102.     }
  1103.     else
  1104.     {
  1105.     int maxIndex, k;
  1106.  
  1107.     maxIndex = dimensions[whichIndex];
  1108.     if (maxIndex > 0)
  1109.     {
  1110.         /*It's real, do it*/
  1111.         for (k = 0; k < maxIndex; ++k)
  1112.         {
  1113.         indices[whichIndex] = k;
  1114.         FillBuckets(whichField, whichIndex + 1, maxNIndices, dimensions, indices);
  1115.         }
  1116.     }
  1117.     else
  1118.     {
  1119.         /*Descend nude*/
  1120.         FillBuckets(whichField, whichIndex + 1, maxNIndices, dimensions, indices);
  1121.     }
  1122.     }
  1123. }
  1124.  
  1125. #ifdef PROTO
  1126. static int MaxComponentIndices(int whichField, int whichComp)
  1127. #else
  1128. static int MaxComponentIndices(whichField, whichComp)
  1129. int whichField;
  1130. int whichComp;
  1131. #endif
  1132. /*Returns the maximum number of indices in whichComp of whichField*/
  1133. {
  1134.     int k;
  1135.     int maxNIndices = -1;
  1136.  
  1137.     for (k = 0; k < curFields[whichField] . components[whichComp] . nIndices; ++k)
  1138.     {
  1139.     if (curFields[whichField] . components[whichComp] . indices[k] > maxNIndices)
  1140.     {
  1141.         maxNIndices = curFields[whichField] . components[whichComp] . indices[k];
  1142.     }
  1143.     }
  1144.     return maxNIndices + 1;
  1145. }
  1146.  
  1147. #ifdef PROTO
  1148. static void MakeBuckets(int whichField)
  1149. #else
  1150. static void MakeBuckets(whichField)
  1151. int whichField;
  1152. #endif
  1153. /*Makes the buckets for whichField*/
  1154. {
  1155.     TwoReals *minMax;
  1156.     int whichComp;
  1157.     int k;
  1158.  
  1159.     if (!curFields[whichField] . bucketMinMax)
  1160.     {
  1161.     /*No buckets yet.  Make some*/
  1162.     int nTraversalDims;
  1163.     long *traversalDims;
  1164.     long *traversalIndices;
  1165.  
  1166.     long bucketDim;
  1167.     long nBucketDims;
  1168.     long *bucketDims;
  1169.  
  1170.     long k;
  1171.     long nElements;
  1172.     long nBuckets;
  1173.     Bucket *buckets;
  1174.     real sample;
  1175.     int whichComp, whichDim;
  1176.  
  1177.     minMax = (TwoReals *) Alloc(curFields[whichField] . nComponents * sizeof(TwoReals));
  1178.     curFields[whichField] . bucketMinMax = minMax;
  1179.  
  1180.     nTraversalDims = CountTraversalDims(whichField);
  1181.     if (!nTraversalDims)
  1182.     {
  1183.         return;
  1184.     }
  1185.     traversalDims = (long *) Alloc(nTraversalDims * sizeof(long));
  1186.     GetTraversalDims(whichField, traversalDims);
  1187.     traversalIndices = (long *) Alloc(nTraversalDims * sizeof(long));
  1188.  
  1189.     /*Go through all the samples, setting up the minmax*/
  1190.     for (whichComp = 0; whichComp < curFields[whichField] . nComponents; ++whichComp)
  1191.     {
  1192.         /*Prepare minMax for expansion*/
  1193.         minMax[whichComp][0] = PLUSINF;
  1194.         minMax[whichComp][1] = MINUSINF;
  1195.  
  1196.         /*Zero the indices*/
  1197.         for (k = 0; k < nTraversalDims; ++k)
  1198.         {
  1199.         traversalIndices[k] = 0;
  1200.         }
  1201.  
  1202.         do
  1203.         {
  1204.         /*Sample the location at a point*/
  1205.         sample = SelectFieldComponent(whichField, 0, traversalIndices);
  1206.  
  1207.         if (sample != missingData)
  1208.         {
  1209.             if (sample < minMax[whichComp][0]) minMax[whichComp][0] = sample;
  1210.             if (sample > minMax[whichComp][1]) minMax[whichComp][1] = sample;
  1211.         }
  1212.  
  1213.         /*Advance to next point*/
  1214.         for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  1215.         {
  1216.             if (traversalDims[whichDim] > 0)
  1217.             {
  1218.             if ((++traversalIndices[whichDim]) >= traversalDims[whichDim])
  1219.             {
  1220.                 traversalIndices[whichDim] = 0;
  1221.             }
  1222.             else
  1223.             {
  1224.                 break;
  1225.             }
  1226.             }
  1227.         }
  1228.         } while (whichDim < nTraversalDims); /*Break is based on advance*/
  1229.     }
  1230.  
  1231.     /*Start figuring how to traverse field.*/
  1232.     curFields[whichField] . nBucketIndices = nTraversalDims;
  1233.  
  1234.     /*Calculate the number of elements total*/
  1235.     nElements = 1;
  1236.     for (k = 0; k < nTraversalDims; ++k)
  1237.     {
  1238.         if (traversalDims[k] >= 0)
  1239.         {
  1240.         nElements *= traversalDims[k];
  1241.         }
  1242.     }
  1243.  
  1244.     /*Now that we have the number of elements, calculate a good # of buckets.*/
  1245.     nBuckets = nElements * BUCKETSIZEFACTOR;
  1246.  
  1247.     /*If it's too many to be manageable, back it off*/
  1248.     if (nBuckets > MAXBUCKETSIZE)
  1249.     {
  1250.         nBuckets = MAXBUCKETSIZE;
  1251.     }
  1252.  
  1253.     /*Find a bucket dimension*/
  1254.     bucketDim = (int) pow((double) nBuckets, 1.0 / (double) (curFields[whichField] . nComponents));
  1255.     if (bucketDim <= 0) ++bucketDim;
  1256.  
  1257. #ifdef DEBUG
  1258.     printf("Side dimension = %d\n", bucketDim);
  1259.     printf("Target # buckets = %d\n", nBuckets);
  1260. #endif
  1261.     
  1262.     /*Make bucket dimensions*/
  1263.     bucketDims = (long *) Alloc((curFields[whichField] . nComponents) * sizeof(long));
  1264.     curFields[whichField] . bucketDim = bucketDims;
  1265.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  1266.     {
  1267.         bucketDims[k] = bucketDim;
  1268.     }
  1269.  
  1270.     /*Create and zero the actual bucket array*/
  1271.     buckets = (Bucket *) Alloc(((long) nBuckets) * sizeof(Bucket));
  1272.     curFields[whichField] . buckets = buckets;
  1273.     for (k = 0; k < nBuckets; ++k)
  1274.     {
  1275.         buckets[k] . indices = 0;
  1276.         buckets[k] . samples = 0;
  1277.         buckets[k] . nIndices = 0;
  1278.     }
  1279.  
  1280.     /*Fill the buckets*/
  1281.     for (k = 0; k < nTraversalDims; ++k)
  1282.     {
  1283.         traversalIndices[k] = 0;
  1284.     }
  1285.     FillBuckets(whichField, 0, nTraversalDims, traversalDims, traversalIndices);
  1286.  
  1287. #ifdef DEBUG
  1288.     /*Print out bucket statistics*/
  1289.     {
  1290.         long nFilled, maxFilled;
  1291.         nFilled = 0;
  1292.         maxFilled = 0;
  1293.         for (k = 0; k < nBuckets; ++k)
  1294.         {
  1295.         if (buckets[k] . nIndices)
  1296.         {
  1297.             ++nFilled;
  1298.             if (buckets[k] . nIndices > maxFilled)
  1299.             maxFilled = buckets[k] . nIndices;
  1300.         }
  1301.         }
  1302.         printf("%ld out of %ld buckets filled (%lg%%)\n",
  1303.         nFilled, nBuckets, ((double) nFilled) / ((double) nBuckets) * 100.0);
  1304.         printf("Maximum bucket size = %ld\n", maxFilled);
  1305.     }
  1306. #endif
  1307.  
  1308.     Free(traversalIndices);
  1309.     Free(traversalDims);
  1310.     }
  1311. }
  1312.  
  1313. #ifdef PROTO
  1314. void SBS2(int whichField, long powerIndices[], long centerIndices[],
  1315.       long shell, int whichIndex, long bestIndex[],
  1316.       real *bestGuess, real sample[])
  1317. #else
  1318. void SBS2(whichField, powerIndices, centerIndices,
  1319.       shell, whichIndex, bestIndex,
  1320.       bestGuess, sample)
  1321. int whichField;
  1322. long powerIndices[];
  1323. long centerIndices[];
  1324. long shell;
  1325. int whichIndex;
  1326. long bestIndex[];
  1327. real *bestGuess;
  1328. real sample[];
  1329. #endif
  1330. /*Powerset recursive helper for SearchBucketForSample.  Searches a shell 
  1331.   shell wide around centerIndices, comparing each sample with bestGuess,
  1332.   returning bestIndex if found.  whichIndex is the current index, used for
  1333.   the powerset, done through powerIndices*/
  1334. {
  1335.     long i, k;
  1336.     register int nComponents;
  1337.  
  1338.     nComponents = curFields[whichField] . nComponents;
  1339.  
  1340.     if (whichIndex >= nComponents)
  1341.     {
  1342.     real d2;    /*Distance squared*/
  1343.     real d;        /*Distance*/
  1344.     register Bucket *bucket;
  1345.     long offset;
  1346.  
  1347.     /*Bottomed out.  Test to see if we're in the right shell*/
  1348.     for (k = 0; k < nComponents; ++k)
  1349.     {
  1350.         if (ABS(powerIndices[k] - centerIndices[k]) != shell)
  1351.         {
  1352.         /*Not on this shell, so don't do anything.*/
  1353.         return;
  1354.         }
  1355.     }
  1356.  
  1357.     /*Calculate the offset*/
  1358.     offset = CalcBucketOffset(whichField, powerIndices);
  1359.  
  1360.     /*Get the bucket*/
  1361.     bucket = &(curFields[whichField] . buckets[offset]);
  1362.  
  1363.     /*Search for better match*/
  1364.     for (k = 0; k < bucket -> nIndices; ++k)
  1365.     {
  1366.         /*Calculate distance*/
  1367.         d2 = 0.0;
  1368.  
  1369.         for (i = 0; i < nComponents; ++i)
  1370.         {
  1371.         if (bucket -> samples[k * nComponents + i] == missingData)
  1372.         {
  1373.             break;
  1374.         }
  1375.         d = bucket -> samples[k * nComponents + i] - sample[k];
  1376.         d2 += d * d;
  1377.         }
  1378.  
  1379.         if (i >= nComponents)
  1380.         {
  1381.         /*It completed a distance*/
  1382.         if (d2 < *bestGuess)
  1383.         {
  1384.             /*Improved guess, copy index*/
  1385.             *bestGuess = d2;
  1386.             for (i = 0; i < curFields[whichField] . nBucketIndices; ++i)
  1387.             {
  1388.             bestIndex[i] =
  1389.                 bucket -> indices[k * curFields[whichField] . nBucketIndices + i];
  1390.             }
  1391.         }
  1392.         }
  1393.     }
  1394.     }
  1395.     else
  1396.     {
  1397.     long min, max;
  1398.  
  1399.     /*Go down powerset*/
  1400.     min = centerIndices[whichIndex] - shell;
  1401.     if (min < 0)
  1402.     {
  1403.         min = 0;
  1404.     }
  1405.     max = centerIndices[whichIndex] + shell;
  1406.     if (max >= curFields[whichField] . bucketDim[whichIndex])
  1407.     {
  1408.         max = curFields[whichField] . bucketDim[whichIndex] - 1;
  1409.     }
  1410.     for (powerIndices[whichIndex] = min;
  1411.          powerIndices[whichIndex] <= max;
  1412.          ++powerIndices[whichIndex])
  1413.     {
  1414.         SBS2(whichField, powerIndices, centerIndices,
  1415.         shell, whichIndex + 1, bestIndex,
  1416.         bestGuess, sample);
  1417.     }
  1418.     }
  1419. }
  1420.  
  1421. #ifdef PROTO
  1422. Bool SearchBucketForSample(int whichField, real indices[], 
  1423.     long bucketIndices[], real sample[])
  1424. #else
  1425. Bool SearchBucketForSample(whichField, indices, bucketIndices, sample)
  1426. int whichField;
  1427. real indices[];
  1428. long bucketIndices[];
  1429. real sample[];
  1430. #endif
  1431. /*Searches the buckets of whichField for sample and returns in indices.
  1432.   bucketIndices is the first guess and is assumed to be DISPOSABLE.
  1433. */
  1434. {
  1435.     long *bestIndex;        /*Best index so far*/
  1436.     long *powerIndices;        /*Power indices*/
  1437.     long k;
  1438.     long shell, nShells;
  1439.     real bestGuess;        /*Best guess so far*/
  1440.  
  1441.     bestIndex = (long *) Alloc(sizeof(long) * curFields[whichField] . nBucketIndices);
  1442.     powerIndices = (long *) Alloc(sizeof(long) * curFields[whichField] . nComponents);
  1443.  
  1444.     /*Calculate the maximum number of shells to use*/
  1445.     nShells = 0;
  1446.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  1447.     {
  1448.     if (bucketIndices[k] > nShells)
  1449.     {
  1450.         nShells = bucketIndices[k];
  1451.     }
  1452.     if (curFields[whichField] . bucketDim[k] - bucketIndices[k] > bucketIndices[k])
  1453.     {
  1454.         nShells = curFields[whichField] . bucketDim[k] - bucketIndices[k];
  1455.     }
  1456.     }
  1457.  
  1458.     /*Now search for a match in progressively widening shells*/
  1459.     bestGuess = plusInf;
  1460.  
  1461.     for (shell = 0; shell < nShells; ++shell)
  1462.     {
  1463.     SBS2(whichField, powerIndices, bucketIndices, shell, 0, bestIndex, &bestGuess, sample);
  1464.     if (bestGuess < plusInf)
  1465.     {
  1466.         break;
  1467.     }
  1468.     }
  1469.  
  1470.     /*Put the best index into indices*/
  1471.     for (k = 0; k < curFields[whichField] . nBucketIndices; ++k)
  1472.     {
  1473.     indices[k] = bestIndex[k];
  1474.     }
  1475.  
  1476.     Free(powerIndices);
  1477.     Free(bestIndex);
  1478.  
  1479.     return (bestGuess < plusInf) ? true : false;
  1480. }
  1481.  
  1482.  
  1483. #ifdef PROTO
  1484. Bool SampleToTopIndex(int whichField, int nIndices, real indices[], 
  1485.         int nComponents, real sample[])
  1486. #else
  1487. Bool SampleToTopIndex(whichField, nIndices, indices, nComponents, sample)
  1488. int whichField;
  1489. int nIndices;
  1490. real indices[];
  1491. int nComponents;
  1492. real sample[];
  1493. #endif
  1494. /*Finds and returns in indices the closest index in whichField to sample.
  1495.   The arrays had better be big enough*/
  1496. {
  1497.     int i, comp, k, index, myIndex;
  1498.     int indicesAssigned;
  1499.     Bool succeed;
  1500.     Bool inHere, otherFree, others;
  1501.     long *longIndices;
  1502.     long *bucketIndices;
  1503.     real retVal;
  1504.  
  1505.     /*Find the number of components, should be == size of sample*/
  1506.     if (nComponents < curFields[whichField] . nComponents)
  1507.     {
  1508.     ReportError("SampleToTopIndex", "Not enough components passed");
  1509.     return false;
  1510.     }
  1511.  
  1512.     longIndices = Alloc(nIndices * sizeof(long));
  1513.  
  1514.     /*Make all indices Free*/
  1515.     for (k = 0; k < nIndices; ++k)
  1516.     {
  1517.     indices[k] = -1.0;
  1518.     longIndices[k] = -1;
  1519.     }
  1520.  
  1521.     /*Number of indices which have been assigned, start at 0*/
  1522.     indicesAssigned = 0;
  1523.  
  1524.     do
  1525.     {
  1526.     succeed = false;
  1527.     /*Search for an index and component such that
  1528.       1) The index is Free
  1529.       2) The index appears in the component
  1530.       3) No other component is Free*/
  1531.  
  1532.     for (i = 0; i < nIndices; ++i)
  1533.     {
  1534.         /*See if it's Free*/
  1535.         if (longIndices[i] < 0)
  1536.         {
  1537.         /*See if it appears in any components with Free index*/
  1538.         for (comp = 0; comp < curFields[whichField] . nComponents; ++comp)
  1539.         {
  1540.             inHere = others = otherFree = false;
  1541.             for (k = 0;
  1542.              k < curFields[whichField] . components[comp] . nIndices;
  1543.              ++k)
  1544.             {
  1545.             index = curFields[whichField] . components[comp] . indices[k];
  1546.             if (index == i)
  1547.             {
  1548.                 myIndex = k;
  1549.                 inHere = true;
  1550.             }
  1551.             else if (index >= 0)
  1552.             {
  1553.                 if (longIndices[index] < 0)
  1554.                 {
  1555.                 otherFree = true;
  1556.                 }
  1557.                 else
  1558.                 {
  1559.                 others = true;
  1560.                 }
  1561.             }
  1562.             }
  1563.  
  1564.             if (inHere && !otherFree)
  1565.             {
  1566.             /*Found one which is Free*/
  1567.  
  1568.             if (!others &&
  1569.                 0 == (curFields[whichField] . components[comp] . flags & (CF_MONOTONIC | CF_NOTMONOTONIC)))
  1570.             {
  1571.                 int testo;
  1572.                 real next, last;
  1573.  
  1574.                 testo = 0;
  1575.                 
  1576.                 /*Might be monotonic.  Let's check*/
  1577.                 longIndices[i] = 0;
  1578.                 last = SelectFieldComponent(whichField, comp, longIndices);
  1579.                 for (longIndices[i] = 1;
  1580.                      longIndices[i] < curFields[whichField] . components[comp] . dimensions[myIndex];
  1581.                      ++(longIndices[i]))
  1582.                 {
  1583.                 next = SelectFieldComponent(whichField, comp, longIndices);
  1584.                 if (next > last)
  1585.                 {
  1586.                     testo |= 1;
  1587.                 }
  1588.                 else if (last > next)
  1589.                 {
  1590.                     testo |= 2;
  1591.                 }
  1592.                 last = next;
  1593.                 }
  1594.                 if (testo < 3)
  1595.                 {
  1596.                 curFields[whichField] . components[comp] . flags |= CF_MONOTONIC;
  1597.                 }
  1598.                 else
  1599.                 {
  1600.                 curFields[whichField] . components[comp] . flags |= CF_NOTMONOTONIC;
  1601.                 }
  1602.             }
  1603.  
  1604.             /*Hey!  Found it!*/
  1605.  
  1606.             if (curFields[whichField] . components[comp] . flags & CF_MONOTONIC)
  1607.             {
  1608.                 long beg, end, mid;
  1609.                 real begFit, endFit, midFit, diff1, diff2;
  1610.  
  1611.                 beg = 0;
  1612.                 end = curFields[whichField] . components[comp] . dimensions[myIndex] - 1;
  1613.                 longIndices[i] = beg;
  1614.                 begFit = SelectFieldComponent(whichField, comp, longIndices);
  1615.                 longIndices[i] = end;
  1616.                 endFit = SelectFieldComponent(whichField, comp, longIndices);
  1617.  
  1618.                 if (begFit < endFit)
  1619.                 {
  1620.                 /*Positive monotonic*/
  1621.                 if (sample[comp] <= begFit)
  1622.                 {
  1623.                     longIndices[i] = beg;
  1624.                     indices[i] = beg;
  1625.                 }
  1626.                 else if (sample[comp] >= endFit)
  1627.                 {
  1628.                     longIndices[i] = end;
  1629.                     indices[i] = end;
  1630.                 }
  1631.                 else
  1632.                 {
  1633.                     while (beg + 1 < end)
  1634.                     {
  1635.                     mid = (beg + end) / 2;
  1636.                     if (mid <= beg) mid = beg + 1;
  1637.                     else if (mid >= end) mid = end - 1;
  1638.                     longIndices[i] = mid;
  1639.                     midFit = SelectFieldComponent(whichField, comp, longIndices);
  1640.                     if (midFit > sample[comp])
  1641.                     {
  1642.                         endFit = midFit;
  1643.                         end = mid;
  1644.                     }
  1645.                     else
  1646.                     {
  1647.                         begFit = midFit;
  1648.                         beg = mid;
  1649.                     }
  1650.                     }
  1651.                     diff1 = begFit - sample[comp];
  1652.                     diff1 = ABS(diff1);
  1653.                     diff2 = endFit - sample[comp];
  1654.                     diff2 = ABS(diff2);
  1655.                     longIndices[i] = (diff1 > diff2) ? end : beg;
  1656.                     indices[i] = ((beg * diff2) + (end * diff1)) / (diff1 + diff2);
  1657.                 }
  1658.                 succeed = true;
  1659.                 ++indicesAssigned;
  1660.                 }
  1661.                 else
  1662.                 {
  1663.                 /*Negative monotonic*/
  1664.                 if (sample[comp] >= begFit)
  1665.                 {
  1666.                     longIndices[i] = beg;
  1667.                     indices[i] = beg;
  1668.                 }
  1669.                 else if (sample[comp] <= endFit)
  1670.                 {
  1671.                     longIndices[i] = end;
  1672.                     indices[i] = end;
  1673.                 }
  1674.                 else
  1675.                 {
  1676.                     while (beg + 1 < end)
  1677.                     {
  1678.                     mid = (beg + end) / 2;
  1679.                     if (mid >= beg) mid = beg + 1;
  1680.                     else if (mid <= end) mid = end - 1;
  1681.                     longIndices[i] = mid;
  1682.                     midFit = SelectFieldComponent(whichField, comp, longIndices);
  1683.                     if (midFit < sample[comp])
  1684.                     {
  1685.                         endFit = midFit;
  1686.                         end = mid;
  1687.                     }
  1688.                     else
  1689.                     {
  1690.                         begFit = midFit;
  1691.                         beg = mid;
  1692.                     }
  1693.                     }
  1694.                     diff1 = begFit - sample[comp];
  1695.                     diff1 = ABS(diff1);
  1696.                     diff2 = endFit - sample[comp];
  1697.                     diff2 = ABS(diff2);
  1698.                     longIndices[i] = (diff1 > diff2) ? end : beg;
  1699.                     indices[i] = ((beg * diff2) + (end * diff1)) / (diff1 + diff2);
  1700.                 }
  1701.                 succeed = true;
  1702.                 ++indicesAssigned;
  1703.                 }
  1704.             }
  1705.             else
  1706.             {
  1707.                 /*It's not monotonic.  Do a linear search*/
  1708.                 long bestFit;
  1709.                 real bestDist;
  1710.                 real diff;
  1711.  
  1712.                 succeed = true;
  1713.                 ++indicesAssigned;
  1714.  
  1715.                 longIndices[i] = 0;
  1716.                 bestFit = 0;
  1717.                 diff = SelectFieldComponent(whichField, comp, longIndices) -
  1718.                 sample[comp];
  1719.                 bestDist = ABS(diff);
  1720.  
  1721.                 for (longIndices[i] = 1;
  1722.                  longIndices[i] < curFields[whichField] . components[comp] . dimensions[myIndex];
  1723.                  ++(longIndices[i]))
  1724.                 {
  1725.                 diff = SelectFieldComponent(whichField, comp, longIndices) -
  1726.                     sample[comp];
  1727.                 diff = ABS(diff);
  1728.                 if (diff < bestDist)
  1729.                 {
  1730.                     bestDist = diff;
  1731.                     bestFit = longIndices[i];
  1732.                 }
  1733.                 }
  1734.                 longIndices[i] = bestFit;
  1735.                 if (longIndices[i] <= 0)
  1736.                 {
  1737.                 real sCenter, sPlus;
  1738.                 /*At left, see if it's between 0 and 1*/
  1739.  
  1740.                 sCenter = SelectFieldComponent(whichField, comp, longIndices);
  1741.                 ++longIndices[i];
  1742.                 sPlus = SelectFieldComponent(whichField, comp, longIndices);
  1743.                 --longIndices[i];
  1744.                 if (sCenter <= sample[comp] <= sPlus)
  1745.                 {
  1746.                     indices[i] =
  1747.                     (sPlus - sample[comp]) * longIndices[i] +
  1748.                     (sample[comp] - sCenter) * (longIndices[i] + 1);
  1749.                 }
  1750.                 else if (sPlus <= sample[comp] <= sCenter)
  1751.                 {
  1752.                     indices[i] =
  1753.                     (sCenter - sample[comp]) * longIndices[i] +
  1754.                     (sample[comp] - sPlus) * (longIndices[i] + 1);
  1755.                 }
  1756.                 else
  1757.                 {
  1758.                     indices[i] = longIndices[i];
  1759.                 }
  1760.                 }
  1761.                 else if (longIndices[i] >= curFields[whichField] . components[comp] . dimensions[myIndex])
  1762.                 {
  1763.                 real sCenter, sMinus;
  1764.                 /*At right, see if it's between right and right - 1*/
  1765.  
  1766.                 sCenter = SelectFieldComponent(whichField, comp, longIndices);
  1767.                 --longIndices[i];
  1768.                 sMinus = SelectFieldComponent(whichField, comp, longIndices);
  1769.                 ++longIndices[i];
  1770.                 if (sCenter <= sample[comp] <= sMinus)
  1771.                 {
  1772.                     indices[i] =
  1773.                     (sMinus - sample[comp]) * longIndices[i] +
  1774.                     (sample[comp] - sCenter) * (longIndices[i] - 1);
  1775.                 }
  1776.                 else if (sMinus <= sample[comp] <= sCenter)
  1777.                 {
  1778.                     indices[i] =
  1779.                     (sCenter - sample[comp]) * longIndices[i] +
  1780.                     (sample[comp] - sMinus) * (longIndices[i] - 1);
  1781.                 }
  1782.                 else
  1783.                 {
  1784.                     indices[i] = longIndices[i];
  1785.                 }
  1786.                 }
  1787.                 else
  1788.                 {
  1789.                 real sCenter, sMinus, sPlus;
  1790.                 /*It's in the center*/
  1791.                 sCenter = SelectFieldComponent(whichField, comp, longIndices);
  1792.                 --longIndices[i];
  1793.                 sMinus = SelectFieldComponent(whichField, comp, longIndices);
  1794.                 ++longIndices[i];
  1795.                 ++longIndices[i];
  1796.                 sPlus = SelectFieldComponent(whichField, comp, longIndices);
  1797.                 --longIndices[i];
  1798.                 if (sCenter <= sample[comp] <= sPlus)
  1799.                 {
  1800.                     indices[i] =
  1801.                     (sPlus - sample[comp]) * longIndices[i] +
  1802.                     (sample[comp] - sCenter) * (longIndices[i] + 1);
  1803.                 }
  1804.                 else if (sPlus <= sample[comp] <= sCenter)
  1805.                 {
  1806.                     indices[i] =
  1807.                     (sCenter - sample[comp]) * longIndices[i] +
  1808.                     (sample[comp] - sPlus) * (longIndices[i] + 1);
  1809.                 }
  1810.                 else if (sCenter <= sample[comp] <= sMinus)
  1811.                 {
  1812.                     indices[i] =
  1813.                     (sMinus - sample[comp]) * longIndices[i] +
  1814.                     (sample[comp] - sCenter) * (longIndices[i] - 1);
  1815.                 }
  1816.                 else if (sMinus <= sample[comp] <= sCenter)
  1817.                 {
  1818.                     indices[i] =
  1819.                     (sCenter - sample[comp]) * longIndices[i] +
  1820.                     (sample[comp] - sMinus) * (longIndices[i] - 1);
  1821.                 }
  1822.                 else
  1823.                 {
  1824.                     indices[i] = longIndices[i];
  1825.                 }
  1826.                 }
  1827.             }
  1828.             }
  1829.         }
  1830.         }
  1831.     }
  1832.     } while (succeed && indicesAssigned < nIndices);
  1833.  
  1834.     Free(longIndices);
  1835.  
  1836.     if (indicesAssigned >= nIndices)
  1837.     {
  1838.     /*Success*/
  1839.     return true;
  1840.     }
  1841.  
  1842.     /*Fell through, so have to use bucket approach*/
  1843.     MakeBuckets(whichField);
  1844.  
  1845.     /*Calculate initial guess*/
  1846.     bucketIndices = (long *) Alloc(sizeof(long) * curFields[whichField] . nComponents);
  1847.  
  1848.     CalcBucketIndices(bucketIndices, whichField,
  1849.             curFields[whichField] . nComponents,
  1850.             sample);
  1851.  
  1852.     retVal = SearchBucketForSample(whichField, indices, bucketIndices, sample);
  1853.     Free(bucketIndices);
  1854.     return retVal;
  1855. }
  1856.  
  1857. #ifdef PROTO
  1858. real SelectFieldComponent(int whichField, int whichComponent, long indices[])
  1859. #else
  1860. real SelectFieldComponent(whichField, whichComponent, indices)
  1861. int whichField;
  1862. int whichComponent;
  1863. long indices[];
  1864. #endif
  1865. /*Selects a field component given indices into it.  There had better be enough
  1866.   indices*/
  1867. {
  1868.  
  1869.     if (curFields[whichField] . groupInterp)
  1870.     {
  1871.     /*Group interpolation*/
  1872.     register int k;
  1873.     register long offset1 = 0, offset2 = 0;    /*Offsets into the data*/
  1874.     register Component *component1;        /*The current components*/
  1875.     register Component *component2;
  1876.     real s1, s2;
  1877.     real w1, w2;
  1878.  
  1879.     /*Get the current component*/
  1880.     component1 = &(curFields[whichField] . components[whichComponent]);
  1881.  
  1882.     w1 = curFields[whichField] . weight;
  1883.  
  1884.     /*Calculate the offset*/
  1885.     for (k = 0; k < component1 -> nIndices; ++k)
  1886.     {
  1887.         register int whichIndex;
  1888.  
  1889.         whichIndex = component1 -> indices[k];
  1890.  
  1891.         if (whichIndex >= 0)
  1892.         {
  1893.         offset1 += component1 -> steps[k] * indices[whichIndex];
  1894.         }
  1895.     }
  1896.  
  1897.     s1 = component1 -> dataCompressed ?
  1898.          component1 -> cTable[component1 -> data . comp[offset1]] :
  1899.          component1 -> data . unComp[offset1];
  1900.  
  1901.     if (curFields[whichField] . substMissing && (s1 == missingData))
  1902.     {
  1903.         s1 = curFields[whichField] . missingVal;
  1904.     }
  1905.  
  1906.     /*Get the current component*/
  1907.     component2 = &(curFields[whichField + MAXNCURFIELDS] . components[whichComponent]);
  1908.  
  1909.     w2 = curFields[whichField + MAXNCURFIELDS] . weight;
  1910.  
  1911.     /*Calculate the offset*/
  1912.     for (k = 0; k < component2 -> nIndices; ++k)
  1913.     {
  1914.         register int whichIndex;
  1915.  
  1916.         whichIndex = component2 -> indices[k];
  1917.  
  1918.         if (whichIndex >= 0)
  1919.         {
  1920.         offset2 += component2 -> steps[k] * indices[whichIndex];
  1921.         }
  1922.     }
  1923.  
  1924.     s2 = component2 -> dataCompressed ?
  1925.          component2 -> cTable[component2 -> data . comp[offset2]] :
  1926.          component2 -> data . unComp[offset2];
  1927.  
  1928.     if (curFields[whichField] . substMissing && (s2 == missingData))
  1929.     {
  1930.         s2 = curFields[whichField] . missingVal;
  1931.     }
  1932.  
  1933.     if (s1 == missingData)
  1934.     {
  1935.         if (w2 >= w1)
  1936.         {
  1937.         return s2;
  1938.         }
  1939.         else
  1940.         {
  1941.         return missingData;
  1942.         }
  1943.     }
  1944.     else if (s2 == missingData)
  1945.     {
  1946.         if (w1 >= w2)
  1947.         {
  1948.         return s1;
  1949.         }
  1950.         else
  1951.         {
  1952.         return missingData;
  1953.         }
  1954.     }
  1955.     else
  1956.     {
  1957.         return (s1 * w1 + s2 * w2) / (w1 + w2);
  1958.     }
  1959.     }
  1960.     else
  1961.     {
  1962.     register int k;
  1963.     register long offset = 0;        /*Offset into the data*/
  1964.     register Component *component;    /*The current component*/
  1965.     real s;
  1966.  
  1967.     /*Get the current component*/
  1968.     component = &(curFields[whichField] . components[whichComponent]);
  1969.  
  1970.     /*Calculate the offset*/
  1971.     for (k = 0; k < component -> nIndices; ++k)
  1972.     {
  1973.         register int whichIndex;
  1974.  
  1975.         whichIndex = component -> indices[k];
  1976.  
  1977.         if (whichIndex >= 0)
  1978.         {
  1979.         offset += component -> steps[k] * indices[whichIndex];
  1980.         }
  1981.     }
  1982.  
  1983.     s = component -> dataCompressed ?
  1984.          component -> cTable[component -> data . comp[offset]] :
  1985.          component -> data . unComp[offset];
  1986.  
  1987.     if (curFields[whichField] . substMissing && (s == missingData))
  1988.     {
  1989.         return curFields[whichField] . missingVal;
  1990.     }
  1991.     return s;
  1992.     }
  1993. }
  1994.  
  1995. #ifdef PROTO
  1996. real SelectFieldScalar(int whichField, long indices[])
  1997. #else
  1998. real SelectFieldScalar(whichField, indices)
  1999. int whichField;
  2000. long indices[];
  2001. #endif
  2002. /*Selects a scalar value from whichField using indices*/
  2003. {
  2004.     if (curFields[whichField] . nComponents < 2)
  2005.     {
  2006.     return SelectFieldComponent(whichField, 0, indices);
  2007.     }
  2008.     else
  2009.     {
  2010.     real squareSum, d;
  2011.     int whichComponent;
  2012.  
  2013.     squareSum = 0.0;
  2014.     for (whichComponent = 0;
  2015.         whichComponent < curFields[whichField] . nComponents;
  2016.         ++whichComponent)
  2017.     {
  2018.         d = SelectFieldComponent(whichField, whichComponent, indices);
  2019.  
  2020.         if (d == missingData)
  2021.         {
  2022.         return missingData;
  2023.         }
  2024.         squareSum += SQUARE(d);
  2025.     }
  2026.     return rsqrt(squareSum);
  2027.     }
  2028. }
  2029.  
  2030. #ifdef PROTO
  2031. real InterpolateFieldComponent(int whichField, int whichComponent, real indices[])
  2032. #else
  2033. real InterpolateFieldComponent(whichField, whichComponent, indices)
  2034. int whichField;
  2035. int whichComponent;
  2036. real indices[];
  2037. #endif
  2038. /*Interpolates a component at a set of real topological indices*/
  2039. {
  2040.     register int i, k;
  2041.     register long test;
  2042.     register Component *component;    /*The current component*/
  2043.     real retVal;
  2044.     register int whichIndex;
  2045.     register real index;
  2046.  
  2047.     component = &(curFields[whichField] . components[whichComponent]);
  2048.  
  2049.     for (k = 0; k < component -> nIndices; ++k)
  2050.     {
  2051.     whichIndex = component -> indices[k];
  2052.  
  2053.     if (whichIndex >= 0)
  2054.     {
  2055.         index = indices[whichIndex];
  2056.  
  2057.         test = index;
  2058.         if (index != (real) test)
  2059.         {
  2060.         /*It's non integral*/
  2061.  
  2062.         if (index < -0.5 ||
  2063.             index > ((real) component -> dimensions[whichIndex]) - 0.5)
  2064.         {
  2065.             /*It's way outside*/
  2066.             return missingData;
  2067.         }
  2068.         else
  2069.         {
  2070.             /*It's between two vertices*/
  2071.             long i1, i2;
  2072.             real v1, v2;
  2073.             real *tempIndices;
  2074.             int copyIndex;
  2075.  
  2076.             i1 = test;
  2077.             i2 = i1 + 1;
  2078.  
  2079.             tempIndices = (real *) Alloc(MaxComponentIndices(whichField, whichComponent) * sizeof(real));
  2080.  
  2081.             /*Copy all the indices*/
  2082.             for (i = 0; i < component -> nIndices; ++i)
  2083.             {
  2084.             copyIndex = component -> indices[i];
  2085.             if (copyIndex >= 0)
  2086.             {
  2087.                 tempIndices[copyIndex] = indices[copyIndex];
  2088.             }
  2089.             }
  2090.  
  2091.             /*Now get the two values for the two indices*/
  2092.             tempIndices[whichIndex] = i1;
  2093.             v1 = InterpolateFieldComponent(whichField, whichComponent, tempIndices);
  2094.             tempIndices[whichIndex] = i2;
  2095.             v2 = InterpolateFieldComponent(whichField, whichComponent, tempIndices);
  2096.  
  2097.             Free(tempIndices);
  2098.  
  2099.             /*Now return an interpolation*/
  2100.             if (v1 == missingData)
  2101.             {
  2102.             if (v2 == missingData)
  2103.             {
  2104.                 return missingData;
  2105.             }
  2106.             else
  2107.             {
  2108.                 if (i2 - index <= index - i1)
  2109.                 {
  2110.                 return v2;
  2111.                 }
  2112.                 else
  2113.                 {
  2114.                 return missingData;
  2115.                 }
  2116.             }
  2117.             }
  2118.             else if (v2 == missingData)
  2119.             {
  2120.             if (index - i1 <= i2 - index)
  2121.             {
  2122.                 return v1;
  2123.             }
  2124.             else
  2125.             {
  2126.                 return missingData;
  2127.             }
  2128.             }
  2129.             else
  2130.             {
  2131.             return (index - i1) * v2 + (i2 - index) * v1;
  2132.             }
  2133.         }
  2134.         }
  2135.     }
  2136.     }
  2137.  
  2138.     /*If we fell through here, it must be smack dab on a vertex.  Just get it*/
  2139.     {
  2140.     long *tempIndices;
  2141.  
  2142.     tempIndices = (long *) Alloc(MaxComponentIndices(whichField, whichComponent) * sizeof(long));
  2143.     for (k = 0; k < component -> nIndices; ++k)
  2144.     {
  2145.         whichIndex = component -> indices[k];
  2146.         if (whichIndex >= 0)
  2147.         {
  2148.             tempIndices[whichIndex] = indices[whichIndex];
  2149.         }
  2150.     }
  2151.     retVal = SelectFieldComponent(whichField, whichComponent, tempIndices);
  2152.     Free(tempIndices);
  2153.     return retVal;
  2154.     }
  2155. }
  2156.  
  2157. #ifdef PROTO
  2158. real InterpolateFieldScalar(int whichField, real indices[])
  2159. #else
  2160. real InterpolateFieldScalar(whichField, indices)
  2161. int whichField;
  2162. real indices[];
  2163. #endif
  2164. /*Interpolates between scalar values*/
  2165. {
  2166.     if (curFields[whichField] . nComponents < 2)
  2167.     {
  2168.     return InterpolateFieldComponent(whichField, 0, indices);
  2169.     }
  2170.     else
  2171.     {
  2172.     real squareSum;
  2173.     int k;
  2174.     real d;
  2175.  
  2176.     squareSum = 0.0;
  2177.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  2178.     {
  2179.         d = InterpolateFieldComponent(whichField, k, indices);
  2180.         if (d == missingData) return missingData;
  2181.         squareSum += SQUARE(d);
  2182.     }
  2183.  
  2184.     return rsqrt(squareSum);
  2185.     }
  2186. }
  2187.  
  2188. long GetComponentOffset(whichField, whichComponent, indices)
  2189. int whichField;
  2190. int whichComponent;
  2191. long indices[];
  2192. /*Get the offset into a field component given indices into it.  There had better be enough
  2193.   indices*/
  2194. {
  2195.     register int k;
  2196.     register long offset = 0;        /*Offset into the data*/
  2197.     register Component *component;    /*The current component*/
  2198.  
  2199.     /*Get the current component*/
  2200.     if (whichComponent < 0 || 
  2201.     whichComponent > curFields[whichField] . nComponents)
  2202.     {
  2203.     return 0;
  2204.     }
  2205.     component = &(curFields[whichField] . components[whichComponent]);
  2206.  
  2207.     /*Calculate the offset*/
  2208.     for (k = 0; k < component -> nIndices; ++k)
  2209.     {
  2210.     register int whichIndex;
  2211.     register long index;
  2212.     
  2213.     whichIndex = component -> indices[k];
  2214.  
  2215.     if (whichIndex >= 0)
  2216.     {
  2217.         index = indices[whichIndex];
  2218.         if (index < 0 || index > component -> dimensions[k])
  2219.         {
  2220.         return 0;
  2221.         }
  2222.     }
  2223.  
  2224.     offset += component -> steps[k] * index;
  2225.     }
  2226.     return offset;
  2227. }
  2228.  
  2229.  
  2230. #ifdef PROTO
  2231. void PutFieldComponent(int whichField, int whichComponent, long indices[], real data)
  2232. #else
  2233. void PutFieldComponent(whichField, whichComponent, indices, data)
  2234. int whichField;
  2235. int whichComponent;
  2236. long indices[];
  2237. real data;
  2238. #endif
  2239. /*Puts data into a field component given indices into it.  There had better be enough
  2240.   indices*/
  2241. {
  2242.     register int k;
  2243.     register long offset = 0;        /*Offset into the data*/
  2244.     register Component *component;    /*The current component*/
  2245.  
  2246.     /*Get the current component*/
  2247.     if (whichComponent < 0 || 
  2248.     whichComponent > curFields[whichField] . nComponents)
  2249.     {
  2250.     return;
  2251.     }
  2252.     component = &(curFields[whichField] . components[whichComponent]);
  2253.  
  2254.     /*Calculate the offset*/
  2255.     for (k = 0; k < component -> nIndices; ++k)
  2256.     {
  2257.     register int whichIndex;
  2258.     register long index;
  2259.     
  2260.     whichIndex = component -> indices[k];
  2261.  
  2262.     if (whichIndex >= 0)
  2263.     {
  2264.         index = indices[whichIndex];
  2265.         if (index < 0 || index > component -> dimensions[k])
  2266.         {
  2267.         return;
  2268.         }
  2269.  
  2270.         offset += component -> steps[k] * index;
  2271.     }
  2272.     }
  2273.     if (component -> dataCompressed)
  2274.     {
  2275.     ReportError("PutFieldComponent", "Cannot put in a compressed field");
  2276.     }
  2277.     else
  2278.     {
  2279.     component -> data . unComp [offset] = data;
  2280.     }
  2281. }
  2282.  
  2283. #ifdef PROTO
  2284. void PutCompressedFieldComponent(int whichField, int whichComponent, long indices[], unsigned char data)
  2285. #else
  2286. void PutCompressedFieldComponent(whichField, whichComponent, indices, data)
  2287. int whichField;
  2288. int whichComponent;
  2289. long indices[];
  2290. unsigned char data;
  2291. #endif
  2292. /*Puts compressed data into a field component given indices into it.  There had better be enough
  2293.   indices*/
  2294. {
  2295.     register int k;
  2296.     register long offset = 0;        /*Offset into the data*/
  2297.     register Component *component;    /*The current component*/
  2298.  
  2299.     /*Get the current component*/
  2300.     if (whichComponent < 0 || 
  2301.     whichComponent > curFields[whichField] . nComponents)
  2302.     {
  2303.     return;
  2304.     }
  2305.     component = &(curFields[whichField] . components[whichComponent]);
  2306.  
  2307.     /*Calculate the offset*/
  2308.     for (k = 0; k < component -> nIndices; ++k)
  2309.     {
  2310.     register int whichIndex;
  2311.     register long index;
  2312.     
  2313.     whichIndex = component -> indices[k];
  2314.  
  2315.     if (whichIndex >= 0)
  2316.     {
  2317.         index = indices[whichIndex];
  2318.         if (index < 0 || index > component -> dimensions[k])
  2319.         {
  2320.         return;
  2321.         }
  2322.  
  2323.         offset += component -> steps[k] * index;
  2324.     }
  2325.     }
  2326.     if (!component -> dataCompressed)
  2327.     {
  2328.     ReportError("PutCompressedFieldComponent", "Cannot put in an uncompressed field");
  2329.     }
  2330.     else
  2331.     {
  2332.     component -> data . comp[offset] = data;
  2333.     }
  2334. }
  2335.  
  2336. #ifdef PROTO
  2337. void StuffIJPlane(real *dest, int whichField, int whichComponent, long indices[])
  2338. #else
  2339. void StuffIJPlane(dest, whichField, whichComponent, indices)
  2340. real *dest;
  2341. int whichField;
  2342. int whichComponent;
  2343. long indices[];
  2344. #endif
  2345. /*Stuffs the ij plane with its lower left corner defined by indices into 
  2346.   dest.  Takes data from the specified field, which had better have enough 
  2347.   components.  There had better be enough indices.  This does not check
  2348.   validity of the indices.  Samples are placed in dest as if j moving
  2349.   fastest, i.e., dest[i][j]*/
  2350. {
  2351.  
  2352.     if (curFields[whichField] . groupInterp)
  2353.     {
  2354.     /*A bunch of samples*/
  2355.     int k;
  2356.     register long baseOffset1 = 0;        /*Base offset into the data*/
  2357.     register long baseOffset2 = 0;        /*Base offset into the data*/
  2358.     register long runningOffset1 = 0;    /*Running offset into the data*/
  2359.     register long runningOffset2 = 0;    /*Running offset into the data*/
  2360.     register long iStep1 = 0, jStep1 = 0;    /*Step in the i and j directions*/
  2361.     register long iStep2 = 0, jStep2 = 0;    /*Step in the i and j directions*/
  2362.     register long iDim1, jDim1;        /*Dimensions in the i and j directions*/
  2363.     register long iDim2, jDim2;        /*Dimensions in the i and j directions*/
  2364.     register Component *component1;        /*The current component*/
  2365.     register Component *component2;        /*The current component*/
  2366.     register long destOffset = 0;        /*Offset into destination*/
  2367.     register long i, j;
  2368.     register real s1, s2;
  2369.     register real w1, w2;
  2370.     register real missingVal;
  2371.     Bool substMissing;
  2372.  
  2373.     substMissing = curFields[whichField] . substMissing;
  2374.  
  2375.     missingVal = curFields[whichField] . missingVal;
  2376.  
  2377.     w1 = curFields[whichField] . weight;
  2378.     w2 = curFields[whichField + MAXNCURFIELDS] . weight;
  2379.  
  2380.     /*Get the current components*/
  2381.     component1 = &(curFields[whichField] . components[whichComponent]);
  2382.     component2 = &(curFields[whichField + MAXNCURFIELDS] . components[whichComponent]);
  2383.  
  2384.     /*Calculate the baseOffsets*/
  2385.     baseOffset1 = 0;
  2386.     for (k = 0; k < component1 -> nIndices; ++k)
  2387.     {
  2388.         register int whichIndex;
  2389.         register long index;
  2390.         
  2391.         whichIndex = component1 -> indices[k];
  2392.  
  2393.         if (whichIndex >= 0)
  2394.         {
  2395.         index = indices[whichIndex];
  2396.         if (whichIndex == 0)
  2397.         {
  2398.             /*I component*/
  2399.             iDim1 = component1 -> dimensions[k];
  2400.             iStep1 = component1 -> steps[k];
  2401.             baseOffset1 += iStep1 * index;
  2402.         }
  2403.         else if (whichIndex == 1)
  2404.         {
  2405.             /*J component*/
  2406.             jDim1 = component1 -> dimensions[k];
  2407.             jStep1 = component1 -> steps[k];
  2408.             baseOffset1 += jStep1 * index;
  2409.         }
  2410.         else
  2411.         {
  2412.             baseOffset1 += component1 -> steps[k] * index;
  2413.         }
  2414.         }
  2415.     }
  2416.  
  2417.     baseOffset2 = 0;
  2418.     for (k = 0; k < component2 -> nIndices; ++k)
  2419.     {
  2420.         register int whichIndex;
  2421.         register long index;
  2422.         
  2423.         whichIndex = component2 -> indices[k];
  2424.  
  2425.         if (whichIndex >= 0)
  2426.         {
  2427.         index = indices[whichIndex];
  2428.         if (whichIndex == 0)
  2429.         {
  2430.             /*I component*/
  2431.             iDim2 = component2 -> dimensions[k];
  2432.             iStep2 = component2 -> steps[k];
  2433.             baseOffset2 += iStep2 * index;
  2434.         }
  2435.         else if (whichIndex == 1)
  2436.         {
  2437.             /*J component*/
  2438.             jDim2 = component2 -> dimensions[k];
  2439.             jStep2 = component2 -> steps[k];
  2440.             baseOffset2 += jStep2 * index;
  2441.         }
  2442.         else
  2443.         {
  2444.             baseOffset2 += component2 -> steps[k] * index;
  2445.         }
  2446.         }
  2447.     }
  2448.  
  2449.     if (iDim1 != iDim2 || jDim1 != jDim2)
  2450.     {
  2451.         ReportError("StuffIJPlane", "Dimension mismatch");
  2452.         return;
  2453.     }
  2454.  
  2455.         for (i = indices[0]; i < iDim1; ++i)
  2456.         {
  2457.         runningOffset1 = baseOffset1;
  2458.         runningOffset2 = baseOffset2;
  2459.  
  2460.         for (j = indices[1]; j < jDim1; ++j)
  2461.         {
  2462.             if (component1 -> dataCompressed)
  2463.             {
  2464.             s1 = component1 -> cTable[component1 -> data . comp[runningOffset1]];
  2465.             }
  2466.             else
  2467.             {
  2468.             s1 = component1 -> data . unComp[runningOffset1];
  2469.             }
  2470.  
  2471.             if (substMissing && s1 == missingData)
  2472.             {
  2473.             s1 = missingVal;
  2474.             }
  2475.  
  2476.             if (component2 -> dataCompressed)
  2477.             {
  2478.             s2 = component2 -> cTable[component2 -> data . comp[runningOffset2]];
  2479.             }
  2480.             else
  2481.             {
  2482.             s2 = component2 -> data . unComp[runningOffset2];
  2483.             }
  2484.  
  2485.             if (substMissing && s2 == missingData)
  2486.             {
  2487.             s2 = missingVal;
  2488.             }
  2489.  
  2490.             if (s1 == missingData)
  2491.             {
  2492.             if (w2 >= w1)
  2493.             {
  2494.                 dest[destOffset] = s2;
  2495.             }
  2496.             else
  2497.             {
  2498.                 dest[destOffset] = missingData;
  2499.             }
  2500.             }
  2501.             else if (s2 == missingData)
  2502.             {
  2503.             if (w1 >= w2)
  2504.             {
  2505.                 dest[destOffset] = s1;
  2506.             }
  2507.             else
  2508.             {
  2509.                 dest[destOffset] = missingData;
  2510.             }
  2511.             }
  2512.             else
  2513.             {
  2514.             dest[destOffset] = (s1 * w1 + s2 * w2) / (w1 + w2);
  2515.             }
  2516.             
  2517.             ++destOffset;
  2518.             runningOffset1 += jStep1;
  2519.             runningOffset2 += jStep2;
  2520.         }
  2521.  
  2522.         baseOffset1 += iStep1;
  2523.         baseOffset2 += iStep2;
  2524.         }
  2525.     }
  2526.     else
  2527.     {
  2528.     /*Just one sample*/
  2529.     int k;
  2530.     register long baseOffset = 0;        /*Base offset into the data*/
  2531.     register long runningOffset = 0;    /*Running offset into the data*/
  2532.     register long iStep = 0, jStep = 0;    /*Step in the i and j directions*/
  2533.     register long iDim, jDim;        /*Dimensions in the i and j directions*/
  2534.     register Component *component;        /*The current component*/
  2535.     register long destOffset = 0;        /*Offset into destination*/
  2536.     register long i, j;
  2537.     register real s;
  2538.     register real missingVal;
  2539.     Bool substMissing;
  2540.  
  2541.     substMissing = curFields[whichField] . substMissing;
  2542.     missingVal = curFields[whichField] . missingVal;
  2543.  
  2544.     /*Get the current component*/
  2545.     component = &(curFields[whichField] . components[whichComponent]);
  2546.  
  2547.     /*Calculate the baseOffset*/
  2548.     baseOffset = 0;
  2549.     for (k = 0; k < component -> nIndices; ++k)
  2550.     {
  2551.         register int whichIndex;
  2552.         register long index;
  2553.         
  2554.         whichIndex = component -> indices[k];
  2555.  
  2556.         if (whichIndex >= 0)
  2557.         {
  2558.         index = indices[whichIndex];
  2559.         if (whichIndex == 0)
  2560.         {
  2561.             /*I component*/
  2562.             iDim = component -> dimensions[k];
  2563.             iStep = component -> steps[k];
  2564.             baseOffset += iStep * index;
  2565.         }
  2566.         else if (whichIndex == 1)
  2567.         {
  2568.             /*J component*/
  2569.             jDim = component -> dimensions[k];
  2570.             jStep = component -> steps[k];
  2571.             baseOffset += jStep * index;
  2572.         }
  2573.         else
  2574.         {
  2575.             baseOffset += component -> steps[k] * index;
  2576.         }
  2577.         }
  2578.     }
  2579.  
  2580.     if (component -> dataCompressed)
  2581.     {
  2582.         for (i = indices[0]; i < iDim; ++i)
  2583.         {
  2584.         runningOffset = baseOffset;
  2585.  
  2586.         for (j = indices[1]; j < jDim; ++j)
  2587.         {
  2588.             s = component -> cTable[component -> data . comp[runningOffset]];
  2589.  
  2590.             if (substMissing && s == missingData)
  2591.             {
  2592.             s = missingVal;
  2593.             }
  2594.  
  2595.             dest[destOffset] = s;
  2596.         
  2597.             ++destOffset;
  2598.             runningOffset += jStep;
  2599.         }
  2600.  
  2601.         baseOffset += iStep;
  2602.         }
  2603.     }
  2604.     else
  2605.     {
  2606.         for (i = indices[0]; i < iDim; ++i)
  2607.         {
  2608.         runningOffset = baseOffset;
  2609.  
  2610.         for (j = indices[1]; j < jDim; ++j)
  2611.         {
  2612.             s = component -> data . unComp[runningOffset];
  2613.  
  2614.             if (substMissing && s == missingData)
  2615.             {
  2616.             s = missingVal;
  2617.             }
  2618.  
  2619.             dest[destOffset] = s;
  2620.         
  2621.             ++destOffset;
  2622.             runningOffset += jStep;
  2623.         }
  2624.  
  2625.         baseOffset += iStep;
  2626.         }
  2627.     }
  2628.     }
  2629. }
  2630.  
  2631. Bool SetCurField(whichField, field)
  2632. int whichField;
  2633. ObjPtr field;
  2634. /*Sets current field whichField to field.  Returns true iff it did*/
  2635. {
  2636.     FuncTyp method;
  2637.  
  2638.     /*Clean the field before setting it*/
  2639.     CleanCurField(whichField);
  2640.     CleanCurField(whichField + MAXNCURFIELDS);
  2641.  
  2642.     curFields[whichField] . topDim = GetTopDim(field);
  2643.     curFields[whichField] . fieldObj = field;
  2644.  
  2645.     method = GetMethodSurely("SetCurField", field, REGISTERFIELD);
  2646.     if (method)
  2647.     {
  2648.     ObjPtr result;
  2649.     result = (*method)(field, whichField);
  2650.     if (IsTrue(result))
  2651.     {
  2652.         /*See if it's appropriate to set the idiot flag*/
  2653.         long whichComponent;
  2654.         register Component *component;
  2655.         int k;
  2656.  
  2657.         curFields[whichField] . idiotFlag = true;
  2658.  
  2659.         if (curFields[whichField] . groupInterp)
  2660.         {
  2661.         curFields[whichField] . idiotFlag = false;
  2662.         }
  2663.  
  2664.         for (whichComponent = 0;
  2665.          whichComponent < curFields[whichField] . nComponents;
  2666.          ++whichComponent)
  2667.         {
  2668.         component = &(curFields[whichField] . components[whichComponent]);
  2669.         if (curFields[whichField] . topDim != 1)
  2670.         {
  2671.             curFields[whichField] . idiotFlag = false;
  2672.             break;
  2673.         }
  2674.  
  2675.         if (curFields[whichField] . components[whichComponent] . dataCompressed)
  2676.         {
  2677.             curFields[whichField] . idiotFlag = false;
  2678.             break;
  2679.         }
  2680.  
  2681.         if (curFields[whichField] . topDim !=
  2682.             component -> nIndices)
  2683.         {
  2684.             curFields[whichField] . idiotFlag = false;
  2685.             break;
  2686.         }
  2687.  
  2688.         for (k = component -> nIndices - 1; k >= 0; --k)
  2689.         {
  2690.             if (component -> indices[k] != k)
  2691.             {
  2692.             curFields[whichField] . idiotFlag = false;
  2693.             break;
  2694.             }
  2695.             if (component -> steps[k] !=
  2696.             ((k == component -> nIndices - 1) ?
  2697.                 1 :
  2698.                 component -> dimensions[k + 1] * component -> steps[k + 1]))
  2699.             {
  2700.             curFields[whichField] . idiotFlag = false;
  2701.             break;
  2702.             }
  2703.         }
  2704.         }
  2705.  
  2706.         return true;
  2707.     }
  2708.     else
  2709.     {
  2710.         return false;
  2711.     }
  2712.     }
  2713.     else
  2714.     {
  2715.     return false;
  2716.     }
  2717. }
  2718.  
  2719. Bool SetCurForm(whichField, field)
  2720. int whichField;
  2721. ObjPtr field;
  2722. /*Sets current field whichField to the data form of field*/
  2723. {
  2724.     FuncTyp method;
  2725.  
  2726.     CleanCurField(whichField);
  2727.     CleanCurField(whichField + MAXNCURFIELDS);
  2728.  
  2729.     curFields[whichField] . topDim = GetTopDim(field);
  2730.     curFields[whichField] . fieldObj = GetVar(field, DATAFORM);
  2731.  
  2732.     method = GetMethodSurely("SetCurField", field, REGISTERFORM);
  2733.     if (method)
  2734.     {
  2735.     ObjPtr result;
  2736.     result = (*method)(field, whichField);
  2737.     if (IsTrue(result))
  2738.     {
  2739.         /*See if it's appropriate to set the idiot flag*/
  2740.         long whichComponent;
  2741.         register Component *component;
  2742.         int k;
  2743.  
  2744.         curFields[whichField] . idiotFlag = true;
  2745.  
  2746.         for (whichComponent = 0;
  2747.          whichComponent < curFields[whichField] . nComponents;
  2748.          ++whichComponent)
  2749.         {
  2750.         component = &(curFields[whichField] . components[whichComponent]);
  2751.         if (curFields[whichField] . topDim !=
  2752.             component -> nIndices)
  2753.         {
  2754.             curFields[whichField] . idiotFlag = false;
  2755.             break;
  2756.         }
  2757.  
  2758.         if (curFields[whichField] . topDim != 1)
  2759.         {
  2760.             curFields[whichField] . idiotFlag = false;
  2761.             break;
  2762.         }
  2763.  
  2764.         for (k = component -> nIndices - 1; k >= 0; --k)
  2765.         {
  2766.             if (component -> indices[k] != k)
  2767.             {
  2768.             curFields[whichField] . idiotFlag = false;
  2769.             break;
  2770.             }
  2771.             if (component -> steps[k] !=
  2772.             ((k == component -> nIndices - 1) ?
  2773.                 1 :
  2774.                 component -> dimensions[k + 1] * component -> steps[k + 1]))
  2775.             {
  2776.             curFields[whichField] . idiotFlag = false;
  2777.             break;
  2778.             }
  2779.         }
  2780.         }
  2781.  
  2782.         return true;
  2783.     }
  2784.     else
  2785.     {
  2786.         return false;
  2787.     }
  2788.      }
  2789.     return false;
  2790. }
  2791.  
  2792. ObjPtr RegisterDatasetForm(dataset, whichField)
  2793. int whichField;
  2794. ObjPtr dataset;
  2795. /*Registers the form of a dataset in whichField*/
  2796. {
  2797.     ObjPtr dataForm;
  2798.  
  2799.     MakeVar(dataset, DATAFORM);
  2800.     dataForm = GetVar(dataset, DATAFORM);
  2801.     if (dataForm)
  2802.     {
  2803.     return SetCurField(whichField, dataForm) ? ObjTrue : ObjFalse;
  2804.     }
  2805.     ReportError("RegisterDatasetForm", "No DATAFORM");
  2806.     return ObjFalse;
  2807. }
  2808.  
  2809. Bool RegisterComponent(whichField, whichComponent, field)
  2810. int whichField, whichComponent;
  2811. ObjPtr field;
  2812. /*Registers field as whichComponent of whichField*/
  2813. {
  2814.     FuncTyp method;
  2815.  
  2816.     if (whichComponent < 0 || whichComponent >= curFields[whichField] . nComponents)
  2817.     {
  2818.     ReportError("RegisterComponent", "Component number out of range");
  2819.     return false;
  2820.     }
  2821.  
  2822.     method = GetMethodSurely("RegisterComponent", field, REGISTERCOMP);
  2823.     if (method)
  2824.     {
  2825.     ObjPtr result;
  2826.     result = (*method)(field, whichField, whichComponent);
  2827.     return IsTrue(result) ? true : false;
  2828.     }
  2829.     return false;
  2830. }
  2831.  
  2832. void DatasetChanged(dataset)
  2833. ObjPtr dataset;
  2834. /*Alerts the system that a dataset has changed*/
  2835. {
  2836.     SetVar(dataset, CHANGED, ObjTrue);
  2837.     globalDataset = dataset;
  2838.     ForAllVisWindows(ChangeClockForDataset);
  2839. }
  2840.  
  2841. static ObjPtr DatasetInvalid(dataset)
  2842. ObjPtr dataset;
  2843. /*Invals a dataset*/
  2844. {
  2845.     DatasetChanged(dataset);
  2846.     return ObjTrue;
  2847. }
  2848.  
  2849. static ObjPtr HideDatasetWindow(window)
  2850. ObjPtr window;
  2851. /*Hide a dataset window, just return OK*/
  2852. {
  2853.     return ObjTrue;
  2854. }
  2855.  
  2856. static ObjPtr DropInPaletteCorral(corral, object, x, y)
  2857. ObjPtr corral, object;
  2858. int x, y;
  2859. /*Drops an icon in a palette corral*/
  2860. {
  2861.     ObjPtr dataset;
  2862.     ObjPtr palette;
  2863.     ObjPtr icon;
  2864.     ObjPtr name;
  2865.     ObjPtr defaultIcon;
  2866.     ObjPtr contents;
  2867.     ObjPtr button;
  2868.  
  2869.     /*Find the visualization object*/
  2870.     dataset = GetObjectVar("DropInPaletteCorral", corral, REPOBJ);
  2871.     if (!dataset)
  2872.     {
  2873.     return ObjFalse;
  2874.     }
  2875.  
  2876.     /*Get the field object*/
  2877.     palette = GetVar(object, REPOBJ);
  2878.     if (!palette)
  2879.     {
  2880.     return ObjFalse;
  2881.     }
  2882.     if (!IsPalette(palette))
  2883.     {
  2884.     WarnUser(CW_NOTPALETTEERROR);
  2885.     return ObjFalse;
  2886.     }
  2887.  
  2888.     /*Create an icon for it*/
  2889.     name = GetStringVar("DropInPaletteCorral", palette, NAME);
  2890.     if (!name)
  2891.     {
  2892.     return ObjFalse;
  2893.     }
  2894.  
  2895.     defaultIcon = GetVar(palette, DEFAULTICON);
  2896.     if (defaultIcon)
  2897.     {
  2898.     ObjPtr locArray;
  2899.     real loc[2];
  2900.     icon = NewObject(defaultIcon, 0);
  2901.     SetVar(icon, NAME, name);
  2902.     loc[0] = x;
  2903.     loc[1] = y;
  2904.     locArray = NewRealArray(1, 2L);
  2905.     CArray2Array(locArray, loc);
  2906.     SetVar(icon, ICONLOC, locArray);
  2907.     }
  2908.     else
  2909.     {
  2910.     icon = NewIcon(x, y, ICONQUESTION, GetString(name));
  2911.     }
  2912.     
  2913.     /*Make the icon point to the palette*/
  2914.     SetVar(icon, REPOBJ, palette);
  2915.  
  2916.     /*Make it the only icon in the corral*/
  2917.     contents = NewList();
  2918.     PrefixList(contents, icon);
  2919.     SetVar(corral, CONTENTS, contents);
  2920.     SetVar(contents, PARENT, corral);
  2921.     SetVar(icon, CORRAL, corral);
  2922.  
  2923.     SetVar(icon, PARENT, corral);
  2924.     RecalcScroll(corral);
  2925.  
  2926.     /*Make this object the colored object*/
  2927.     SetVar(dataset, CPALETTE, palette);
  2928.  
  2929.     ImInvalid(corral);
  2930.     DatasetChanged(dataset);
  2931.  
  2932.     return ObjTrue;
  2933. }
  2934.  
  2935. static ObjPtr AddDatasetControls(object, contents)
  2936. ObjPtr object, contents;
  2937. /*Adds controls for a dataset*/
  2938. {
  2939.     ObjPtr var;
  2940.     ObjPtr corral;
  2941.     long info;
  2942.     ObjPtr textBox, checkBox, icon, palette, name, button;
  2943.     int left, right, bottom, top;
  2944.     char *s;
  2945.  
  2946.     /*Add the info description*/
  2947.     left = MINORBORDER;
  2948.     right = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH - MINORBORDER;
  2949.     top = CWINHEIGHT - MINORBORDER;
  2950.     bottom = MINORBORDER;
  2951.  
  2952.     info = GetDatasetInfo(object);
  2953.  
  2954.     s = tempStr;
  2955.     sprintf(s, "Data: ");
  2956.     while (*s) ++s;
  2957.     if (info & DS_TIMEDEPENDENT)
  2958.     {
  2959.     sprintf(s, "Time-dependent ");
  2960.     }
  2961.     else
  2962.     {
  2963.     sprintf(s, "Static ");
  2964.     }
  2965.  
  2966.     while (*s) ++s;
  2967.     if (info &  (DS_HASGEOMETRY | DS_HASNEWGEOMETRY))
  2968.     {
  2969.     sprintf(s, "geometric data\n");
  2970.     }
  2971.     else
  2972.     {
  2973.     long nSamples, nBytes;
  2974.     long k;
  2975.     long nTraversalDims;
  2976.     long *traversalDims;
  2977.     real *minMax;
  2978.     int nComponents;
  2979.  
  2980.     SetCurField(FIELD1, object);
  2981.     if (info & DS_VECTOR)
  2982.     {
  2983.         nComponents = GetNComponents(FIELD1);
  2984.         sprintf(s, "%d-vector %s\n", nComponents,
  2985.         info & DS_HASFORM ? "field" : "data");
  2986.     }
  2987.     else
  2988.     {
  2989.         nComponents = 1;
  2990.         sprintf(s, "scalar %s\n", info & DS_HASFORM ? "field" : "data");
  2991.     }
  2992.     nTraversalDims = CountTraversalDims(FIELD1);
  2993.     if (nTraversalDims > 0)
  2994.     {
  2995.         Bool compressedP;
  2996.  
  2997.         while (*s) ++s;
  2998.         traversalDims = (long *) Alloc(sizeof(long) * nTraversalDims);
  2999.         GetTraversalDims(FIELD1, traversalDims);
  3000.         nSamples = 1;
  3001.         for (k = 0; k < nTraversalDims; ++k)
  3002.         {
  3003.         nSamples *= traversalDims[k];
  3004.         }
  3005.  
  3006.         compressedP = false;
  3007.         nBytes = 0;
  3008.         for (k = 0; k < nComponents; ++k)
  3009.         {
  3010.         if (curFields[FIELD1] . components[k] . dataCompressed)
  3011.         {
  3012.             compressedP = true;
  3013.             nBytes += nSamples;
  3014.         }
  3015.         else
  3016.         {
  3017.             nBytes += nSamples * sizeof(real);
  3018.         }
  3019.         }
  3020.  
  3021.         sprintf(s, "\tMemory: %ld bytes per time step%s\n", nBytes,
  3022.         compressedP ? ", compresed" : "");
  3023.         
  3024.     }
  3025.     else
  3026.     {
  3027.         while (*s) ++s;
  3028.         sprintf(s, "\tSingle numeric value\n");
  3029.     }
  3030.     while (*s) ++s;
  3031.     MakeVar(object, MINMAX);
  3032.     var = GetVar(object, MINMAX);
  3033.     if (var)
  3034.     {
  3035.         minMax = ELEMENTS(var);
  3036.         sprintf(s, "\tRange: [%g, %g]\n", minMax[0], minMax[1]);
  3037.     }
  3038.     }
  3039.     while (*s) ++s;
  3040.     sprintf(s, "\nGrid: ");
  3041.     while (*s) ++s;
  3042.     if (info & DS_HASFORM)
  3043.     {
  3044.     char *t;
  3045.     long topDim;
  3046.     ObjPtr formObj;
  3047.  
  3048.     sprintf(s, "%d-dimensional %s grid\n", 
  3049.         topDim = GetTopDim(object),
  3050.         info & DS_UNSTRUCTURED ? "unstructured" : "structured");
  3051.  
  3052.     if (0 == (info & DS_UNSTRUCTURED))
  3053.     {
  3054.         ObjPtr dimsArray;
  3055.         int k;
  3056.         real *meat;
  3057.         t = s;
  3058.         while (*t) ++t;
  3059.  
  3060.         MakeVar(object, DATAFORM);
  3061.         formObj = GetVar(object, DATAFORM);
  3062.  
  3063.         dimsArray = GetFixedArrayVar("AddDatasetControls", formObj, DIMENSIONS, 1, topDim);
  3064.         if (dimsArray)
  3065.         {
  3066.         meat = ArrayMeat(dimsArray);
  3067.         for (k = 0; k < topDim; ++k)
  3068.         {
  3069.             sprintf(t, "%g", meat[k]);
  3070.             while (*t) ++t;
  3071.             if (k < topDim - 1)
  3072.             {
  3073.             sprintf(t, " by ");
  3074.             while (*t) ++t;
  3075.             }
  3076.         }
  3077.         sprintf(t, "\n");
  3078.         }
  3079.     }
  3080.     }
  3081.     else
  3082.     {
  3083.     sprintf(s, "none");
  3084.     }
  3085.     while (*s) ++s;
  3086.     textBox = TemplateTextBox(NormalDatasetTemplate, "Info Text", 0, tempStr);
  3087.     PrefixList(contents, textBox);
  3088.     SetVar(textBox, PARENT, contents);
  3089.     SetVar(textBox, UIFONT, NewInt(DCFONT));
  3090.     top = bottom - MAJORBORDER;
  3091.  
  3092.     /*Add the interpolate check box*/
  3093.     if (info & DS_TIMEDEPENDENT)
  3094.     {
  3095.     bottom = top - CHECKBOXHEIGHT;
  3096.     /*Create the interpolate check box*/
  3097.     checkBox = TemplateCheckBox(NormalDatasetTemplate, "Interpolate In Time",
  3098.                    GetPredicate(object, INTERPOLATEP));
  3099.     SetVar(checkBox, HELPSTRING,
  3100.         NewString("If this box is checked, the field will automatically be \
  3101. interpolated in time.  If it is not checked, the time step nearest the current \
  3102. time will always be used.\n"));
  3103.     PrefixList(contents, checkBox);
  3104.     SetVar(checkBox, PARENT, contents);
  3105.     AssocDirectControlWithVar(checkBox, GetVar(object, DATA), INTERPOLATEP);
  3106.     }
  3107.  
  3108.     /*Add in the colors corral*/
  3109.     bottom = MAJORBORDER + BUTTONHEIGHT + MINORBORDER + TEXTBOXHEIGHT + TEXTBOXSEP;
  3110.     top = bottom + ONECORRALHEIGHT;
  3111.     right = left + ONECORRALWIDTH;
  3112.     corral = NewIconCorral(NULLOBJ,
  3113.                left, right, bottom, top,
  3114.                0);
  3115.     SetVar(corral, SINGLECORRAL, ObjTrue);
  3116.     SetVar(corral, TOPDOWN, ObjTrue);
  3117.     SetVar(corral, NAME, NewString("Color Palette"));
  3118.     PrefixList(contents, corral);
  3119.     SetVar(corral, HELPSTRING,
  3120.     NewString("This corral shows the color palette of the data in the dataset.  This \
  3121. may be another dataset.  Right now, you cannot drag any icons \
  3122. into the corral."));
  3123.     SetVar(corral, PARENT, contents);
  3124.     SetVar(corral, REPOBJ, object);
  3125.     SetMethod(corral, DROPINCONTENTS, DropInPaletteCorral);
  3126.  
  3127.     /*Create the source text box*/
  3128.     textBox = NewTextBox(left, right, 
  3129.                 bottom - TEXTBOXSEP - TEXTBOXHEIGHT, bottom - TEXTBOXSEP,
  3130.                 0, "Colors Text", "Color Palette");
  3131.     PrefixList(contents, textBox);
  3132.     SetVar(textBox, PARENT, contents);
  3133.     SetTextAlign(textBox, CENTERALIGN);
  3134.  
  3135.     /*Make a palette icon*/
  3136.     MakeVar(object, CPALETTE);
  3137.     palette = GetVar(object, CPALETTE);
  3138.     if (palette)
  3139.     {
  3140.     MakeVar(palette, NAME);
  3141.     name = GetVar(palette, NAME);
  3142.     icon = GetVar(palette, DEFAULTICON);
  3143.     if (icon)
  3144.     {
  3145.         icon = NewObject(icon, 0);
  3146.         SetVar(icon, NAME, name);
  3147.     }
  3148.     else
  3149.     {
  3150.         icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
  3151.     }
  3152.     SetVar(icon, ICONLOC, NULLOBJ);
  3153.     SetVar(icon, REPOBJ, palette);
  3154.     SetVar(icon, CORRAL, corral);
  3155.     DropIconInCorral(corral, icon);
  3156.     }
  3157.  
  3158.     /*Make a show info button*/
  3159.     button = NewFunctionButton((WinInfoPtr) GetVar(contents, OWNERWINDOW),
  3160.         left, right, 
  3161.         MINORBORDER, MINORBORDER + BUTTONHEIGHT, OF_SHOW_CONTROLS); 
  3162.     if (button)
  3163.     {
  3164.     SetVar(button, PARENT, contents);
  3165.     SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + FLOATINGRIGHT + STICKYLEFT));
  3166.     PrefixList(contents, button);
  3167.     }
  3168.  
  3169.     return ObjTrue;
  3170. }
  3171.  
  3172. #ifdef PROTO
  3173. static int AddControlButton(ObjPtr object, WinInfoPtr controlWindow, ObjPtr controlField, ObjPtr panel, int top)
  3174. #else
  3175. static int AddControlButton(object, controlWindow, controlField, panel, top)
  3176. ObjPtr object;
  3177. WinInfoPtr controlWindow;
  3178. ObjPtr controlField;
  3179. ObjPtr panel;
  3180. int top;
  3181. #endif
  3182. /*Adds a number of control buttons from object into contents in window starting at
  3183.   top.  Returns a new top.*/
  3184. {
  3185.     ObjPtr curObj;
  3186.     ObjPtr icon;
  3187.     ObjPtr contents;
  3188.     Bool firstTime = true;
  3189.  
  3190.     contents = GetVar(controlField, CONTENTS);
  3191.  
  3192.     /*Fill the control field up with buttons*/
  3193.     MakeVar(object, CONTROLICON);
  3194.  
  3195.     curObj = object;
  3196.     icon = NULLOBJ;
  3197.     while (curObj)
  3198.     {
  3199.     if (!icon)
  3200.     {
  3201.         icon = Get1Var(curObj, CONTROLICON);
  3202.     }
  3203.     if (icon)
  3204.     {
  3205.         ObjPtr button;
  3206.         ObjPtr panelContents;
  3207.         FuncTyp method;
  3208.         int whichIcon;
  3209.         char *name;
  3210.         ObjPtr var;
  3211.  
  3212.         /*Give the button a chance to add controls*/
  3213.         method = Get1Method(curObj, ADDCONTROLS);
  3214.         if (method)
  3215.         {
  3216.         var = GetIntVar("ShowVisControls", icon, WHICHICON);
  3217.         if (var)
  3218.         {
  3219.             whichIcon = GetInt(var);
  3220.         }
  3221.         else
  3222.         {
  3223.             whichIcon = ICONQUESTION;
  3224.         }
  3225.  
  3226.         var = GetStringVar("ShowVisControls", icon, NAME);
  3227.         if (var)
  3228.         {
  3229.             name = GetString(var);
  3230.         }
  3231.         else
  3232.         {
  3233.             name = "Unknown";
  3234.         }
  3235.  
  3236.         button = NewIconLabeledButton(0, CWINCCWIDTH, top - CWINICONBUTHEIGHT, top,
  3237.             whichIcon, UIYELLOW, name, BS_PITTED);
  3238.         SetMethod(button, ICONEXTRADRAW, GetMethod(icon, ICONEXTRADRAW));
  3239.         SetVar(button, CONTROLSADDED, ObjTrue);
  3240.         SetMethod(button, CHANGEDVALUE, ChangeControlPanelButton);
  3241.  
  3242.         /*Make a new panel contents just for this button*/
  3243.         panelContents = NewList();
  3244.         PrefixList(panelContents, controlField);
  3245.         SetVar(panelContents, PARENT, panel);
  3246.         SetVar(button, PANELCONTENTS, panelContents);
  3247.         SetVar(button, PANEL, panel);
  3248.         SetVar(panelContents, OWNERWINDOW, (ObjPtr) controlWindow);
  3249.  
  3250.         icon = NULLOBJ;
  3251.         (*method)(object, panelContents);
  3252.         PostfixList(contents, button);
  3253.         SetVar(button, PARENT, controlField);
  3254.         top -= CWINICONBUTHEIGHT + MINORBORDER;
  3255.  
  3256.         if (firstTime)
  3257.         {
  3258.             ObjPtr mainDataset, notes;
  3259.  
  3260.  
  3261.             /*Do the notes*/
  3262.             notes = GetVar(object, NOTES);
  3263.             if (notes)
  3264.             {
  3265.             ObjPtr infoField;
  3266.             ThingListPtr runner;
  3267.         
  3268.             runner = LISTOF(notes);
  3269.             while (runner)
  3270.             {
  3271.                 int l, r, b, t;
  3272.                 char objName[200];
  3273.                 ObjPtr fieldContents;
  3274.  
  3275.                 name = GetString(runner -> thing);
  3276.                 runner = runner -> next;
  3277.         
  3278.                 if (runner)
  3279.                 {
  3280.                 /*Make the info*/
  3281.                 ObjPtr textBox;
  3282.  
  3283.                 button = NewIconLabeledButton(0, CWINCCWIDTH, top - CWINICONBUTHEIGHT, top,
  3284.                         ICONNOTE, UIYELLOW, name, BS_PITTED);
  3285.             
  3286.                 SetMethod(button, CHANGEDVALUE, ChangeControlPanelButton);
  3287.             
  3288.                 /*Make a new panel contents just for this button*/
  3289.                 panelContents = NewList();
  3290.                 PrefixList(panelContents, controlField);
  3291.                 SetVar(panelContents, PARENT, panel);
  3292.                 SetVar(button, PANELCONTENTS, panelContents);
  3293.                 SetVar(button, PARENT, panelContents);
  3294.                 SetVar(button, PANEL, panel);
  3295.                 SetVar(panelContents, OWNERWINDOW, (ObjPtr) controlWindow);
  3296.     
  3297.                 strcpy(objName, name);
  3298.                 strcat(objName, " info field");
  3299.                 infoField = NewControlField(MINORBORDER, 
  3300.                         CWINWIDTH - CORRALBORDER - CWINCORRALWIDTH - MINORBORDER,
  3301.                         MINORBORDER, CWINHEIGHT - MINORBORDER,
  3302.                         objName, OBJECTSFROMTOP | BARRIGHT);    
  3303.                 PrefixList(panelContents, infoField);
  3304.                 SetVar(infoField, PARENT, panel);
  3305.                 SetVar(infoField, BACKGROUND, NewInt(UIGRAY75));
  3306.                 SetVar(infoField, BORDERTYPE, NewInt(1));
  3307.                 fieldContents = GetVar(infoField, CONTENTS);
  3308.     
  3309.                 PostfixList(contents, button);
  3310.                 SetVar(button, PARENT, controlField);
  3311.                 top -= CWINICONBUTHEIGHT + MINORBORDER;
  3312.     
  3313.                 /*Now make the text box inside the window*/
  3314.                 Get2DIntBounds(infoField, &l, &r, &b, &t);
  3315.                 strcpy(objName, name);
  3316.                 strcat(objName, " info text");
  3317.                 textBox = NewTextBox(MINORBORDER, r - l - 2 * MINORBORDER,
  3318.                          -MINORBORDER - 100, /*Will change later*/
  3319.                          -MINORBORDER,
  3320.                          0, objName, GetString(runner -> thing));
  3321.                 Set2DIntBounds(textBox,
  3322.                         MINORBORDER, r - l - 2 * MINORBORDER,
  3323.                         -MINORBORDER - TextHeight(textBox),
  3324.                         -MINORBORDER);
  3325.                 PrefixList(fieldContents, textBox);
  3326.                 SetVar(textBox, PARENT, infoField);
  3327.                 RecalcScroll(infoField);
  3328.  
  3329.                 runner = runner -> next;
  3330.                 }
  3331.             }
  3332.             }
  3333.  
  3334.             firstTime = false;
  3335.             mainDataset = GetVar(object, MAINDATASET);
  3336.             if (mainDataset)
  3337.             {
  3338.             top = AddControlButton(mainDataset, controlWindow, controlField, panel, top);
  3339.             }
  3340.         }
  3341.         }
  3342.     }
  3343.  
  3344.     curObj = ClassOf(curObj);
  3345.     }
  3346.  
  3347.     return top;
  3348. }
  3349.  
  3350. static ObjPtr ShowDatasetControls(object, windowName)
  3351. ObjPtr object;
  3352. char *windowName;
  3353. /*Makes a new control window to control dataset object*/
  3354. {
  3355.     WinInfoPtr controlWindow;
  3356.     ObjPtr var;
  3357.     ObjPtr panel;
  3358.     ObjPtr controlField;
  3359.     ObjPtr contents;
  3360.     int left, right, bottom, top, width;
  3361.     WinInfoPtr dialogExists;
  3362.     ObjPtr icon;
  3363.  
  3364.     dialogExists = DialogExists((WinInfoPtr) object, NewString("Controls"));
  3365.     controlWindow = GetDialog((WinInfoPtr) object, NewString("Controls"), windowName, 
  3366.     CWINWIDTH, CWINHEIGHT, CWINWIDTH, CWINHEIGHT, WINFIXEDSIZE + WINUI);
  3367.     
  3368.     if (!dialogExists)
  3369.     {
  3370.     SetVar((ObjPtr) controlWindow, REPOBJ, object);
  3371.  
  3372.     /*Add in help string*/
  3373.     SetVar((ObjPtr) controlWindow, HELPSTRING,
  3374.         NewString("This window shows controls for a dataset object.  \
  3375. At the right is an icon corral showing a series of icons.  Each icon represents a \
  3376. set of attributes of the visualization object.  On the left are the controls for \
  3377. the selected set of attributes.  \
  3378. Use Help In Context and click on the various controls to find out what they do.  \
  3379. Click on a different icon to choose a different set of attributes."));
  3380.  
  3381.     /*Add in a panel*/
  3382.     panel = NewPanel(greyPanelClass, 0, CWINWIDTH, 0, CWINHEIGHT);
  3383.     if (!panel)
  3384.     {
  3385.         return ObjFalse;
  3386.     }
  3387.     contents = GetVar((ObjPtr) controlWindow, CONTENTS);
  3388.     PrefixList(contents, panel);
  3389.     SetVar(panel, PARENT, (ObjPtr) controlWindow);
  3390.  
  3391.     contents = GetVar(panel, CONTENTS);
  3392.  
  3393.     /*Add in a control field*/
  3394.     controlField = NewControlField(CWINWIDTH - CORRALBORDER - CWINCORRALWIDTH,
  3395.                    CWINWIDTH - CORRALBORDER,
  3396.                    CORRALBORDER,
  3397.                    CWINHEIGHT - CORRALBORDER,
  3398.                 "Dataset Object Attributes", OBJECTSFROMTOP | BARRIGHT);
  3399.     SetVar(controlField, HELPSTRING,
  3400.         NewString("This icon button group shows sets of attributes of the dataset \
  3401. object.  The left side of the panel shows controls for the \
  3402. attribute given by the selected icon button.  To show another set of \
  3403. attributes, press another button."));
  3404.     SetVar(controlField, PARENT, panel);
  3405.     PrefixList(contents, controlField);
  3406.  
  3407.     contents = GetVar(controlField, CONTENTS);
  3408.  
  3409.     top = -MAJORBORDER;
  3410.     AddControlButton(object, controlWindow, controlField, panel, top);
  3411.  
  3412.     /*Adjust the scroll bars*/
  3413.     RecalcScroll(controlField);
  3414.  
  3415.     if (LISTOF(contents))
  3416.     {
  3417.         SetValue(LISTOF(contents) -> thing, NewInt(1));
  3418.         SetVar(controlField, BUTTON, LISTOF(contents) -> thing);
  3419.     }
  3420.     }
  3421.  
  3422.     return (ObjPtr) controlWindow;
  3423. }
  3424.  
  3425. #ifdef PROTO
  3426. void SetAllDatasetTimes(real time)
  3427. #else
  3428. void SetAllDatasetTimes(time)
  3429. real time;
  3430. #endif
  3431. /*Sets the time in all the datasets to time*/
  3432. {
  3433.     ObjPtr datasets;
  3434.     ObjPtr keyList;
  3435.     ThingListPtr runner;
  3436.  
  3437.     /*Search database for datasets*/
  3438.     keyList = NewList();
  3439.     PostfixList(keyList, NewSymbol(CLASSID));
  3440.     PostfixList(keyList, NewInt(CLASS_DATASET));
  3441.  
  3442.     datasets = SearchDatabase(keyList);
  3443.  
  3444.     if (datasets)
  3445.     {
  3446.     runner = LISTOF(datasets);
  3447.     while (runner)
  3448.     {
  3449.         ObjPtr obj, var;
  3450.  
  3451.         obj = GetVar(runner -> thing, DATA);
  3452.         if (obj && IsTimedObj(obj))
  3453.         {
  3454.         var = GetVar(obj, TIME);
  3455.         if (var && (GetReal(var) == time))
  3456.         {
  3457.         }
  3458.         else
  3459.         {
  3460.             SetVar(obj, TIME, NewReal(time));
  3461.             SetVar(runner -> thing, CHANGED, ObjTrue);
  3462.         }
  3463.         }
  3464.         runner = runner -> next;
  3465.     }
  3466.     }
  3467. }
  3468.  
  3469. #ifdef PROTO
  3470. ObjPtr FindDatasetByName(char *name)
  3471. #else
  3472. ObjPtr FindDatasetByName(name)
  3473. char *name;
  3474. #endif
  3475. /*Finds a dataset by its name, returns it or nothing*/
  3476. {
  3477.     ObjPtr datasets;
  3478.     ObjPtr keyList;
  3479.     ThingListPtr runner;
  3480.  
  3481.     /*Search database for datasets*/
  3482.     keyList = NewList();
  3483.     PostfixList(keyList, NewSymbol(CLASSID));
  3484.     PostfixList(keyList, NewInt(CLASS_DATASET));
  3485.     PostfixList(keyList, NewSymbol(NAME));
  3486.     PostfixList(keyList, NewString(name));
  3487.  
  3488.     datasets = SearchDatabase(keyList);
  3489.  
  3490.     if (datasets)
  3491.     {
  3492.     runner = LISTOF(datasets);
  3493.     if (runner)
  3494.     {
  3495.         if (runner -> next)
  3496.         {
  3497.         ReportError("FindDatasetByName", "Warning--duplicate dataset name");
  3498.         }
  3499.         return runner -> thing;
  3500.     }
  3501.     }
  3502.  
  3503.     return NULLOBJ;
  3504. }
  3505.  
  3506. #ifdef PROTO
  3507. Bool InsertDatasetTimeStep(ObjPtr masterDataset, ObjPtr timeSlice, real time)
  3508. #else
  3509. Bool InsertDatasetTimeStep(masterDataset, timeSlice, time)
  3510. ObjPtr masterDataset, timeSlice;
  3511. real time;
  3512. #endif
  3513. /*Inserts a dataset time step into a master dataset*/
  3514. {
  3515.     /*Add on to an existing dataset*/
  3516.     InsertTimeSlice(GetVar(masterDataset, DATA), NewReal(time), GetVar(timeSlice, DATA));
  3517.  
  3518.     /*Register the dataset as changed*/
  3519.     DatasetChanged(masterDataset);
  3520.     return true;
  3521. }
  3522.  
  3523. #ifdef PROTO
  3524. Bool RegisterTimeDataset(ObjPtr dataset, real time)
  3525. #else
  3526. Bool RegisterTimeDataset(dataset, time)
  3527. ObjPtr dataset;
  3528. real time;
  3529. #endif
  3530. /*Registers a timeslice dataset, creating a new one or appending on to an old one
  3531.   based on time*/
  3532. {
  3533.     ObjPtr var;
  3534.     ObjPtr priorDataset;
  3535.  
  3536.     /*Find out if there already exists a time object like this*/
  3537.     var = GetVar(dataset, NAME);
  3538.     priorDataset = FindDatasetByName(GetString(var));
  3539.     if (priorDataset)
  3540.     {
  3541.     InsertDatasetTimeStep(priorDataset, dataset, time);
  3542.     /*Make the prior dataset the dataset in use for the icon test*/
  3543.     dataset = priorDataset;
  3544.     }
  3545.     else
  3546.     {
  3547.     ObjPtr timeSteps, timeData;
  3548.     /*Make a new dataset*/
  3549.  
  3550.     timeSteps = NewList();
  3551.     timeData = NewList();
  3552.     PrefixList(timeSteps, NewReal(time));
  3553.     PrefixList(timeData, GetVar(dataset, DATA));
  3554.  
  3555.     SetVar(dataset, DATA, NewTimedObject(timeSteps, timeData));
  3556.     RegisterNewDataset(dataset);
  3557.     }
  3558.     return true;
  3559. }
  3560.  
  3561. #ifdef PROTO
  3562. void SetDatasetTimeFormat(ObjPtr dataset, int format)
  3563. #else
  3564. void SetDatasetTimeFormat(dataset, format)
  3565. ObjPtr dataset;
  3566. int format;
  3567. #endif
  3568. /*Sets a dataset's time format*/
  3569. {
  3570.     SetVar(dataset, TIMEFORMAT, NewInt(format));
  3571. }
  3572.  
  3573. #ifdef PROTO
  3574. Bool RegisterNewDataset(ObjPtr dataset)
  3575. #else
  3576. Bool RegisterNewDataset(dataset)
  3577. ObjPtr dataset;
  3578. #endif
  3579. /*Registers a brand new dataset, doesn't look for name or anything*/
  3580. {
  3581.     ObjPtr corral, contents;
  3582.     ThingListPtr runner;
  3583.     WinInfoPtr datasetsWindow;
  3584.     int k;
  3585.     char *name;
  3586.     ObjPtr icon;
  3587.     ObjPtr defaultIcon;
  3588.     ObjPtr var;
  3589.  
  3590.     datasetsWindow = DatasetsWindow();
  3591.     PopWindow(datasetsWindow);
  3592.  
  3593.     IdleAllWindows();
  3594.  
  3595.     LongOperation();
  3596.  
  3597.     /*Tell dataset about its filename and directory*/
  3598.     if (curFileName)
  3599.     {
  3600.     SetVar(dataset, FILENAME, NewString(curFileName));
  3601.     }
  3602.     getcwd(tempStr, TEMPSTRSIZE);
  3603.     SetVar(dataset, DIRECTORY, NewString(tempStr));
  3604.  
  3605.  
  3606.     corral = GetObjectVar("RegisterNewDataset", (ObjPtr) datasetsWindow, CORRAL);
  3607.     MakeVar(dataset, NAME);
  3608.     var = GetStringVar("RegisterNewDataset", dataset, NAME);
  3609.     if (!var) return false;
  3610.     name = GetString(var);
  3611.  
  3612.     k = 1;
  3613.     while (FindDatasetByName(GetString(var)))
  3614.     {
  3615.     ++k;
  3616.     sprintf(tempStr, "%s (%d)", name, k);
  3617.     var = NewString(tempStr); 
  3618.     }
  3619.     if (k > 1)
  3620.     {
  3621.     name = GetString(var);
  3622.     SetVar(dataset, NAME, var);
  3623.     }
  3624.  
  3625.     /*Search for an icon*/
  3626.     contents = GetListVar("RegisterNewDataset", corral, CONTENTS);
  3627.     if (!contents) return false;
  3628.     runner = LISTOF(contents);
  3629.     while (runner)
  3630.     {
  3631.     ObjPtr repObj;
  3632.     repObj = GetVar(runner -> thing, REPOBJ);
  3633.     if (repObj == dataset)
  3634.     {
  3635.         break;
  3636.     }
  3637.     runner = runner -> next;
  3638.     }
  3639.  
  3640.     if (!runner)
  3641.     {
  3642.     /*Must create a new icon*/
  3643.     defaultIcon = GetVar(dataset, DEFAULTICON);
  3644.     if (defaultIcon)
  3645.     {
  3646.         icon = NewObject(defaultIcon, 0);
  3647.         SetVar(icon, NAME, NewString(name));
  3648.     }
  3649.     else
  3650.     {
  3651.         icon = NewIcon(0, 0, ICONQUESTION, name);
  3652.         SetVar(icon, HELPSTRING,
  3653.         NewString("This icon represents a dataset.  You can select it and use the controls \
  3654. in this window to modify or visualize it, or you can drag it into the \
  3655. corral of an existing visualization window to visualize it there."));
  3656.  
  3657.     }
  3658.     SetVar(icon, REPOBJ, dataset);
  3659.     SetVar(icon, CORRAL, corral);
  3660.     SetVar(icon, ICONLOC, dsLocArray);
  3661.     dsLocArray = NULLOBJ;
  3662.     DropIconInCorral(corral, icon);
  3663.     }
  3664.  
  3665.     AddVolObjToDatabase(dataset);
  3666.     return true;
  3667. }
  3668.  
  3669. Bool RegisterDataset(dataset)
  3670. ObjPtr dataset;
  3671. /*Registers dataset as a dataset*/
  3672. {
  3673.     ObjPtr var;
  3674.     char *name;
  3675.     char *sPtr;
  3676.  
  3677.     var = GetStringVar("RegisteDataset", dataset, NAME);
  3678.     if (!var) return false;
  3679.     name = GetString(var);
  3680.  
  3681.     if (timedDatasets)
  3682.     {
  3683.     /*See if there is a time name*/
  3684.     sPtr = name;
  3685.     while (*sPtr)
  3686.     {
  3687.         if (*sPtr == '@')
  3688.         {
  3689.         /*Yes, it's a time slice!*/
  3690.         strncpy(tempStr, name, TEMPSTRSIZE);
  3691.         if (sPtr - name < TEMPSTRSIZE)
  3692.         {
  3693.             tempStr[sPtr - name] = 0;
  3694.         }
  3695.         else
  3696.         {
  3697.             tempStr[TEMPSTRSIZE] = 0;
  3698.         }
  3699.     
  3700.         /*Edit the dataset's name*/
  3701.         var = NewString(tempStr);
  3702.         SetVar(dataset, NAME, var);
  3703.     
  3704.         /*Copy the time*/
  3705.         strncpy(tempStr, sPtr + 1, TEMPSTRSIZE);
  3706.         tempStr[TEMPSTRSIZE] = 0;
  3707.     
  3708.         /*Get the edited name back into name*/
  3709.         name = GetString(var);
  3710.         break;
  3711.         }
  3712.         ++sPtr;
  3713.     }
  3714.     
  3715.     if (*sPtr == '@')
  3716.     {
  3717.         /*It must be a time slice*/
  3718.         real time;
  3719.         int format;
  3720.     
  3721.         /*Go through and parse the time*/
  3722.         if (ParseTime(&time, &format, tempStr) <= 0)
  3723.         {
  3724.         ReportError("RegisterDataset","Bad time format");
  3725.         }
  3726.         SetDatasetTimeFormat(dataset, format);
  3727.         return RegisterTimeDataset(dataset, time);
  3728.     }
  3729.     else
  3730.     {
  3731.         return RegisterNewDataset(dataset);
  3732.     }
  3733.     }
  3734.     else
  3735.     {
  3736.     return RegisterNewDataset(dataset);
  3737.     }
  3738. }
  3739.  
  3740. static ObjPtr DropInDatasetsCorral(corral, icon, x, y)
  3741. ObjPtr corral, icon;
  3742. int x, y;
  3743. /*Drops an icon in a vis corral*/
  3744. {
  3745.     ObjPtr repObj;
  3746.     repObj = GetVar(icon, REPOBJ);
  3747.     if (repObj && IsFile(repObj))
  3748.     {
  3749.     ObjPtr fileName;        /*Name of the file*/
  3750.     ObjPtr fileType;        /*Type of the file*/
  3751.     ObjPtr fileReader;        /*Reader of the file*/
  3752.     FuncTyp method;
  3753.     real loc[2];
  3754.     loc[0] = x;
  3755.     loc[1] = y;
  3756.  
  3757.     fileName = GetVar(repObj, NAME);
  3758.     fileType = GetVar(repObj, FILETYPE);
  3759.     fileReader = GetVar(repObj, READER);
  3760.  
  3761.     if (GetInt(fileType) == DIRFILE)
  3762.     {
  3763.         WarnUser(CW_READDIRERROR);
  3764.         return ObjFalse;
  3765.     }
  3766.     if (!fileName || !fileReader)
  3767.     {
  3768.         WarnUser(CW_FILEFORMATERROR);
  3769.         return ObjFalse;
  3770.     }
  3771.     dsLocArray = NewRealArray(1, 2L);
  3772.     CArray2Array(dsLocArray, loc);
  3773.  
  3774.     method = GetMethod(repObj, OPEN);
  3775.     if (method)
  3776.     {
  3777.         (*method)(repObj);
  3778.     }
  3779.     dsLocArray = NULLOBJ;
  3780.     return ObjTrue;
  3781.     }
  3782.     else
  3783.     {
  3784.     return ObjFalse;
  3785.     }
  3786. }
  3787.  
  3788. WinInfoPtr NewDatasetsWindow(void)
  3789. /*Create a new Datasets window*/
  3790. {
  3791.     WinInfoPtr objWin;
  3792.     ObjPtr panel, contents, corral, button;
  3793.     int l, r, b, t;
  3794.     int bw;
  3795.  
  3796.     /*Create the window*/
  3797.     objWin = NewObjWindow(NULLOBJ, "Datasets", WINUI, DSWINWIDTH, DSWINHEIGHT, SCRWIDTH, SCRHEIGHT);
  3798.     l = 0; r = DSWINWIDTH; b = 0; t = DSWINHEIGHT;
  3799.  
  3800.     /*Set a null but successful HIDE routine*/
  3801.     SetMethod((ObjPtr) objWin, HIDE, HideDatasetWindow);
  3802.  
  3803.     /*Add a help string*/
  3804.     SetVar((ObjPtr) objWin, HELPSTRING, 
  3805.     NewString("This window shows all the datasets that have been opened in \
  3806. Scian."));
  3807.  
  3808.     /*Put in a panel*/
  3809.     panel = NewPanel(greyPanelClass, 0, DSWINWIDTH, 0, DSWINHEIGHT);
  3810.     SetVar(panel, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT +
  3811.                      STICKYBOTTOM + STICKYTOP));
  3812.  
  3813.     contents = GetVar((ObjPtr) objWin, CONTENTS);
  3814.     PrefixList(contents, panel);
  3815.     SetVar(panel, PARENT, (ObjPtr) objWin);
  3816.  
  3817.     /*Put in buttons and an icon corral*/
  3818.     contents = GetListVar("NewDatasetsWindow", panel, CONTENTS);
  3819.     if (!contents)
  3820.     {
  3821.     return 0;
  3822.     }
  3823.     /*Make an icon corral*/
  3824.     corral = NewIconCorral(NULLOBJ, l + MINORBORDER, r - MINORBORDER, b + 3 * MINORBORDER + 2 * BUTTONHEIGHT, t - MINORBORDER, BARRIGHT + BARBOTTOM);
  3825.     SetVar(corral, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT +
  3826.                      STICKYBOTTOM + STICKYTOP));
  3827.     SetVar(corral, TOPDOWN, ObjTrue);
  3828.     SetVar((ObjPtr) objWin, CORRAL, corral);
  3829.     SetVar(corral, NAME, NewString("Datasets Corral"));
  3830.     SetVar(corral, HELPSTRING,
  3831.     NewString("This corral contains icons for all the datasets that have \
  3832. been read into SciAn.  You can visualize, show the controls of, or modify the datasets by selecting \
  3833. some of them and pressing the buttons at the bottom of the window.  You can delete \
  3834. datasets by choosing Delete from the Object menu.  You can also open new datasets by dragging icons from \
  3835. the file window into this corral."));
  3836.     SetMethod(corral, DROPINCONTENTS, DropInDatasetsCorral);
  3837.     PrefixList(contents, corral);
  3838.     SetVar(corral, PARENT, panel);
  3839.  
  3840.     l += MINORBORDER;
  3841.     r -= MINORBORDER;
  3842.     b += 2 * MINORBORDER + BUTTONHEIGHT;
  3843.     t = b + BUTTONHEIGHT;
  3844.     bw = (r - l - MINORBORDER) / 2;
  3845.  
  3846.     /*Make a visualize button*/
  3847.     button = NewFunctionButton(objWin,
  3848.         l, l + bw,
  3849.         b, b + BUTTONHEIGHT, OF_VISUALIZE); 
  3850.     if (button)
  3851.     {
  3852.     SetVar(button, PARENT, panel);
  3853.     SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + STICKYLEFT + FLOATINGRIGHT));
  3854.     PrefixList(contents, button);
  3855.     }
  3856.  
  3857.     /*Make a visualize as... button*/
  3858.     button = NewFunctionButton(objWin,
  3859.         r - bw, r,
  3860.         b, b + BUTTONHEIGHT, OF_VISUALIZE_AS); 
  3861.     if (button)
  3862.     {
  3863.     SetVar(button, PARENT, panel);
  3864.     SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + FLOATINGLEFT + STICKYRIGHT));
  3865.     PrefixList(contents, button);
  3866.     }
  3867.  
  3868.     t = b - MINORBORDER;
  3869.     b = t - BUTTONHEIGHT;
  3870.     /*Make a show info button*/
  3871.     button = NewFunctionButton(objWin,
  3872.         l, l + bw, 
  3873.         b, b + BUTTONHEIGHT, OF_SHOW_CONTROLS); 
  3874.     if (button)
  3875.     {
  3876.     SetVar(button, PARENT, panel);
  3877.     SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + STICKYLEFT + FLOATINGRIGHT));
  3878.     PrefixList(contents, button);
  3879.     }
  3880.  
  3881.     /*Make a modify button*/
  3882.     button = NewFunctionButton(objWin, 
  3883.         r - bw, r,
  3884.         b, b + BUTTONHEIGHT, OF_MODIFY);
  3885.     if (button)
  3886.     {
  3887.     SetVar(button, PARENT, panel);
  3888.     SetVar(button, STICKINESS, NewInt(STICKYBOTTOM + FLOATINGLEFT + STICKYRIGHT));
  3889.     PrefixList(contents, button);
  3890.     }
  3891.  
  3892.     return objWin;
  3893. }
  3894.  
  3895. WinInfoPtr DatasetsWindow()
  3896. /*Returns or creates a datasets window*/
  3897. {
  3898.     WinInfoPtr retVal;
  3899.  
  3900.     retVal = GetWinFromTitle("Datasets");
  3901.     if (!retVal)
  3902.     {
  3903.     retVal = NewDatasetsWindow();
  3904.     }
  3905.     return retVal;
  3906. }
  3907.  
  3908. static ObjPtr GetDataMinMax(object)
  3909. ObjPtr object;
  3910. /*Gets and returns the min and max of the data in object for a dataset*/
  3911. {
  3912.     ObjPtr retVal;
  3913.     retVal = GetVar(object, MINMAX);
  3914.     if (retVal && IsRealArray(retVal) && RANK(retVal) == 1 && DIMS(retVal)[0] == 2)
  3915.     {
  3916.     return retVal;
  3917.     }
  3918.     else
  3919.     {
  3920.     if (GetDatasetInfo(object) &  (DS_HASGEOMETRY | DS_HASNEWGEOMETRY))
  3921.     {
  3922.         real minmax[2];
  3923.         minmax[0] = 0.0;
  3924.         minmax[1] = 1.0;
  3925.         retVal = NewRealArray(1, 2L);
  3926.         CArray2Array(retVal, minmax);
  3927.         SetVar(object, MINMAX, retVal);
  3928.     }
  3929.     else
  3930.     {
  3931.         /*Must be a field*/
  3932.         int nTraversalDims;        /*Number of dimensions to traverse*/
  3933.         int whichDim;        /*Dimension counter*/
  3934.         long *traversalDims = 0;    /*Dimensions of the dataset to traverse*/
  3935.         long *index = 0;        /*Counting index*/
  3936.         real sample;
  3937.         real minmax[2];
  3938.         FuncTyp tempMethod;
  3939.  
  3940.         tempMethod = GetMethod(object, MINMAX);
  3941.         SetMethod(object, MINMAX, (FuncTyp) 0);
  3942.  
  3943.         SetCurField(FIELD5, object);
  3944.  
  3945.         /*Get the information on traversing the dataset*/
  3946.         nTraversalDims = CountTraversalDims(FIELD5);
  3947.         if (nTraversalDims)
  3948.         {
  3949.         traversalDims = (long *) Alloc(sizeof(long) * nTraversalDims);
  3950.         index = (long *) Alloc(sizeof(long) * nTraversalDims);
  3951.         }
  3952.         else
  3953.         {
  3954.         index = (long *) Alloc(sizeof(long));
  3955.         }
  3956.         GetTraversalDims(FIELD5, traversalDims);
  3957.  
  3958.         /*Zero the index*/
  3959.         for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  3960.         {
  3961.         index[whichDim] = 0;
  3962.         }
  3963.  
  3964.         minmax[0] = minmax[1] = missingData;
  3965.  
  3966.         /*Traverse all the points*/
  3967.         do
  3968.         {
  3969.         /*Sample the location at a point*/
  3970.         sample = SelectFieldScalar(FIELD5, index);
  3971.         if (sample != missingData)
  3972.         {
  3973.             if (minmax[0] == missingData)
  3974.             {
  3975.             minmax[0] = sample;
  3976.             }
  3977.             else
  3978.             {
  3979.             minmax[0] = MIN(minmax[0], sample);
  3980.             }
  3981.             if (minmax[1] == missingData)
  3982.             {
  3983.             minmax[1] = sample;
  3984.             }
  3985.             else
  3986.             {
  3987.             minmax[1] = MAX(minmax[1], sample);
  3988.             }
  3989.         }
  3990.  
  3991.         /*Advance to next point*/
  3992.         for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
  3993.         {
  3994.             if (traversalDims[whichDim] > 0)
  3995.             {
  3996.             if ((++index[whichDim]) >= traversalDims[whichDim])
  3997.             {
  3998.                 index[whichDim] = 0;
  3999.             }
  4000.                 else
  4001.             {
  4002.                 break;
  4003.             }
  4004.             }
  4005.         }
  4006.         } while (whichDim < nTraversalDims); /*Break is based on advance*/
  4007.  
  4008.         /*Free up temporary storage*/
  4009.         SAFEFREE(traversalDims);
  4010.         SAFEFREE(index);
  4011.  
  4012.         retVal = NewRealArray(1, 2L);
  4013.         CArray2Array(retVal, minmax);
  4014.         SetVar(object, MINMAX, retVal);
  4015.  
  4016.         SetMethod(object, MINMAX, tempMethod);
  4017.         return retVal;
  4018.     }
  4019.     }
  4020. }
  4021.  
  4022. static ObjPtr MakeDatasetPalette(object)
  4023. ObjPtr object;
  4024. /*Gets a palette for a dataset object*/
  4025. {
  4026.     ObjPtr palette;
  4027.     palette = GetVar(object, CPALETTE);
  4028.     if (!palette)
  4029.     {
  4030.     ObjPtr minMax, directory, name;
  4031.     real min, max, *elements;
  4032.     ObjPtr var;
  4033.  
  4034.     MakeVar(object, MINMAX);
  4035.     minMax = GetVar(object, MINMAX);
  4036.     if (minMax)
  4037.     {
  4038.         elements = ELEMENTS(minMax);
  4039.         min = elements[0];
  4040.         max = elements[1];
  4041.     }
  4042.     else
  4043.     {
  4044.         min = 0.0;
  4045.         max = 1.0;
  4046.     }
  4047.  
  4048.     if (onePalette)
  4049.     {
  4050.         if (commonPalette)
  4051.         {
  4052.         ObjPtr var;
  4053.         var = GetFixedArrayVar("MakeDatasetPalette", commonPalette, MINMAX, 1, 2L);
  4054.         if (var)
  4055.         {
  4056.             min = ((real *) ELEMENTS(var))[0];
  4057.             max = ((real *) ELEMENTS(var))[1];
  4058.         }
  4059.         palette = commonPalette;
  4060.         }
  4061.     }
  4062.     if (!palette)
  4063.     {
  4064.         var = GetVar(object, UNITSNAME);
  4065.         if (var)
  4066.         {
  4067.         palette = UnitsNameToPalette(GetString(var), min, max);
  4068.         }
  4069.         else
  4070.         {
  4071.         palette = UnitsNameToPalette((char *) 0, min, max);
  4072.         }
  4073.         FieldPaletteName(palette, object);
  4074.     }
  4075.  
  4076.     /*If there is a saved palette, use it.*/
  4077.     directory = GetVar(object, DIRECTORY);
  4078.     if (directory)
  4079.     {
  4080.         ReadObjectControls(palette, directory, true);
  4081.         CopyColorsToComponents(palette);
  4082.     }
  4083.  
  4084.     SetVar(object, CPALETTE, palette);
  4085.     if (onePalette)
  4086.     {
  4087.         commonPalette = palette;
  4088.     }
  4089.     }
  4090.     return ObjTrue;
  4091. }
  4092.  
  4093. static ObjPtr GetPlainDatasetInfo(dataset)
  4094. ObjPtr dataset;
  4095. /*Returns a sum of flags defined in ScianDatasets.h giving info on the dataset*/
  4096. {
  4097.     long retVal;
  4098.     ObjPtr data, form, var;
  4099.  
  4100.     retVal = 0;
  4101.     MakeVar(dataset, DATAFORM);
  4102.     if (form = GetVar(dataset, DATAFORM))
  4103.     {
  4104.     retVal |= DS_HASFORM;
  4105.     if (GetPredicate(form, UNSTRUCTURED))
  4106.     {
  4107.         retVal |= DS_UNSTRUCTURED;
  4108.     }
  4109.     }
  4110.     if (data = GetVar(dataset, DATA))
  4111.     {
  4112.     if (IsTimedObj(data))
  4113.     {
  4114.         ObjPtr timeData;
  4115.  
  4116.         retVal |= DS_TIMEDEPENDENT;
  4117.         timeData = GetVar(data, TIMEDATA);
  4118.         if (timeData)
  4119.         {
  4120.         long dimension = 0;
  4121.         data = GetObjectElement(timeData, &dimension);
  4122.         if (IsPicture(data))
  4123.         {
  4124.             retVal |= DS_HASGEOMETRY;
  4125.         }
  4126.         else if (IsGeometry(data))
  4127.         {
  4128.             retVal |= DS_HASNEWGEOMETRY;
  4129.         }
  4130.         else
  4131.         {
  4132.             retVal |= DS_HASFIELD;
  4133.         }
  4134.         }
  4135.         else
  4136.         {
  4137.         return 0;
  4138.         }
  4139.     }
  4140.     else
  4141.     {
  4142.         if (IsPicture(data))
  4143.         {
  4144.         retVal |= DS_HASGEOMETRY;
  4145.         }
  4146.         else if (IsGeometry(data))
  4147.         {
  4148.         retVal |= DS_HASNEWGEOMETRY;
  4149.         }
  4150.         else
  4151.         {
  4152.         retVal |= DS_HASFIELD;
  4153.         }
  4154.     }
  4155.     }
  4156.     if (var = GetVar(dataset, NCOMPONENTS))
  4157.     {
  4158.     retVal |= DS_VECTOR;
  4159.     }
  4160.     return NewInt(retVal);
  4161. }
  4162.  
  4163. int GetTopDim(dataset)
  4164. ObjPtr dataset;
  4165. /*Returns the topological or computational dimensionality of the dataset
  4166.   Returns 0 if it has no topological dimensions*/
  4167. {
  4168.     FuncTyp method;
  4169.     method = GetMethodSurely("GetTopDim", dataset, GETTOPDIM);
  4170.     if (method)
  4171.     {
  4172.     ObjPtr result;
  4173.     result = (*method)(dataset);
  4174.     if (result)
  4175.     {
  4176.         return GetInt(result);
  4177.     }
  4178.     else
  4179.     {
  4180.         ReportError("GetTopDim", "GETTOPDIM did not return dimension");
  4181.         return 0;
  4182.     }
  4183.     }
  4184.     else
  4185.     {
  4186.     return 0;
  4187.     }
  4188. }
  4189.  
  4190. int GetSpatialDim(dataset)
  4191. ObjPtr dataset;
  4192. /*Returns the spatial dimensionality of the dataset
  4193.   Returns 0 if it has no topological dimensions*/
  4194. {
  4195.     FuncTyp method;
  4196.     method = GetMethodSurely("GetSpatialDim", dataset, GETSPATIALDIM);
  4197.     if (method)
  4198.     {
  4199.     ObjPtr result;
  4200.     result = (*method)(dataset);
  4201.     if (result)
  4202.     {
  4203.         return GetInt(result);
  4204.     }
  4205.     else
  4206.     {
  4207.         return 1;
  4208.     }
  4209.     }
  4210.     else
  4211.     {
  4212.     return 1;
  4213.     }
  4214. }
  4215.  
  4216. long GetDatasetInfo(dataset)
  4217. ObjPtr dataset;
  4218. /*Returns the spatial dimensionality of the dataset
  4219.   Returns 0 if it has no topological dimensions*/
  4220. {
  4221.     FuncTyp method;
  4222.     method = GetMethodSurely("GetDatasetInfo", dataset, GETDATASETINFO);
  4223.     if (method)
  4224.     {
  4225.     ObjPtr result;
  4226.     result = (*method)(dataset);
  4227.     if (result)
  4228.     {
  4229.         return GetInt(result);
  4230.     }
  4231.     else
  4232.     {
  4233.         ReportError("GetDatasetInfo", "No info returned from GETDATASETINFO");
  4234.         return 0;
  4235.     }
  4236.     }
  4237.     else
  4238.     {
  4239.     return 0;
  4240.     }
  4241. }
  4242.  
  4243. ObjPtr GetDataFormTopDim(dataForm)
  4244. ObjPtr dataForm;
  4245. /*Returns the topological dimension of dataForm*/
  4246. {
  4247.     ObjPtr dims;
  4248.  
  4249.     dims = GetArrayVar("GetDataFormTopDim", dataForm, DIMENSIONS);
  4250.     if (dims)
  4251.     {
  4252.     if (GetPredicate(dataForm, UNSTRUCTURED))
  4253.     {
  4254.         return NewInt(DIMS(dims)[0] - 1);
  4255.     }
  4256.     else
  4257.     {
  4258.         return NewInt(DIMS(dims)[0]);
  4259.     }
  4260.     }
  4261.     else
  4262.     {
  4263.     return NewInt(0);
  4264.     }
  4265. }
  4266.  
  4267. static ObjPtr GetDatasetTopDim(dataset)
  4268. ObjPtr dataset;
  4269. /*Returns the topological or computational dimensionality of the dataset
  4270.   Returns 0 if it has no topological dimensions*/
  4271. {
  4272.     ObjPtr dataForm;
  4273.     FuncTyp method;
  4274.  
  4275.     MakeVar(dataset, DATAFORM);
  4276.     dataForm = GetVar(dataset, DATAFORM);
  4277.  
  4278.     if (dataForm)
  4279.     {
  4280.     method = GetMethod(dataForm, GETTOPDIM);
  4281.     if (method)
  4282.     {
  4283.         return (*method)(dataForm);
  4284.     }
  4285.     }
  4286.     else
  4287.     {
  4288.     ObjPtr data;
  4289.     /*No data form, must get the top dim of its DATA*/
  4290.     data = GetVar(dataset, DATA);
  4291.     if (data)
  4292.     {
  4293.         method = GetMethod(data, GETTOPDIM);
  4294.         if (method)
  4295.         {
  4296.         return (*method)(data);
  4297.         }
  4298.     }
  4299.     }
  4300.     
  4301.     return NewInt(0);
  4302. }
  4303.  
  4304. static ObjPtr GetDatasetSpatialDim(dataset)
  4305. ObjPtr dataset;
  4306. /*Returns the spatial dimensionality of the dataset*/
  4307. {
  4308.     ObjPtr dataForm;
  4309.     ObjPtr nComponents, bounds;
  4310.  
  4311.     MakeVar(dataset, DATAFORM);
  4312.     dataForm = GetVar(dataset, DATAFORM);
  4313.     if (!dataForm)
  4314.     {
  4315.     return NewInt(0);
  4316.     }
  4317.  
  4318.     nComponents = GetVar(dataForm, NCOMPONENTS);
  4319.     if (nComponents)
  4320.     {
  4321.     return nComponents;
  4322.     }
  4323.  
  4324.     bounds = GetVar(dataForm, BOUNDS);
  4325.     if (bounds)
  4326.     {
  4327.     return NewInt(DIMS(bounds)[0] / 2);
  4328.     }
  4329.     return ObjFalse;
  4330. }
  4331.  
  4332. ObjPtr GetDatasetFormBounds(dataset)
  4333. ObjPtr dataset;
  4334. /*Returns the bounds of the dataset's data form*/
  4335. {
  4336.     ObjPtr dataForm;
  4337.     ObjPtr dims;
  4338.  
  4339.     MakeVar(dataset, DATAFORM);
  4340.     dataForm = GetVar(dataset, DATAFORM);
  4341.     if (!dataForm)
  4342.     {
  4343.     return 0;
  4344.     }
  4345.  
  4346.     dims = GetArrayVar("GetDatasetFormBounds", dataForm, BOUNDS);
  4347.     return dims;
  4348. }
  4349.  
  4350. ObjPtr GetDatasetFormDims(dataset)
  4351. ObjPtr dataset;
  4352. /*Returns the dimensions of the dataset's data form*/
  4353. {
  4354.     FuncTyp method;
  4355.     method = GetMethodSurely("GetDatasetFormDims", dataset, GETFORMDIMS);
  4356.  
  4357.     if (method)
  4358.     {
  4359.     return (*method)(dataset);
  4360.     }
  4361.     else
  4362.     {
  4363.     return NULLOBJ;
  4364.     }
  4365. }
  4366.  
  4367. ObjPtr GetPlainDatasetFormDims(dataset)
  4368. ObjPtr dataset;
  4369. /*Returns the dimensions of the dataset's data form*/
  4370. {
  4371.     ObjPtr dataForm;
  4372.     ObjPtr dims;
  4373.  
  4374.     MakeVar(dataset, DATAFORM);
  4375.     dataForm = GetVar(dataset, DATAFORM);
  4376.     if (!dataForm)
  4377.     {
  4378.     return 0;
  4379.     }
  4380.  
  4381.     dims = GetArrayVar("GetPlainDatasetFormDims", dataForm, DIMENSIONS);
  4382.     return dims;
  4383. }
  4384.  
  4385. ObjPtr GetDatasetKEdges(dataset, k)
  4386. ObjPtr dataset;
  4387. int k;
  4388. /*Returns a list of k-edges of the dataset.  Only works for unstructured 
  4389.   data forms.
  4390. */
  4391. {
  4392.     ObjPtr dataForm;
  4393.  
  4394.     MakeVar(dataset, DATAFORM);
  4395.     dataForm = GetVar(dataset, DATAFORM);
  4396.     if (!dataForm)
  4397.     {
  4398.     return NULLOBJ;
  4399.     }
  4400.     if (k == 1)
  4401.     {
  4402.     return GetVar(dataForm, EDGES);
  4403.     }
  4404.     else if (k == 2)
  4405.     {
  4406.     return GetVar(dataForm, CELLS);
  4407.     }
  4408.     else
  4409.     {
  4410.     ReportError("GetDatasetKEdges", "Edges beyond 2 are not defined");
  4411.     return NULLOBJ;
  4412.     }
  4413. }
  4414.  
  4415. static ObjPtr RegisterDatasetField(dataset, whichField)
  4416. ObjPtr dataset;
  4417. int whichField;
  4418. /*Registers datastet's data as whichField.*/
  4419. {
  4420.     ObjPtr data;
  4421.     ObjPtr var;
  4422.     FuncTyp method;
  4423.  
  4424.     MakeVar(dataset, DATA);
  4425.     data = GetVar(dataset, DATA);
  4426.  
  4427.     if (!data)
  4428.     {
  4429.     ReportError("RegisterDatasetField", "No DATA");
  4430.     return ObjFalse;
  4431.     }
  4432.  
  4433.     /*It's an array or vector.  Stuff it recursively*/
  4434.     method = GetMethodSurely("RegisterDatasetField", data, REGISTERFIELD);
  4435.     if (method)
  4436.     {
  4437.     return (*method)(data, whichField);
  4438.     }
  4439.  
  4440.     return ObjFalse;
  4441. }
  4442.  
  4443. int GetNComponents(whichField)
  4444. int whichField;
  4445. /*Returns the number of components of whichField*/
  4446. {
  4447.     return curFields[whichField] . nComponents;
  4448. }
  4449.  
  4450. int CountComponentDims(whichField, whichComponent)
  4451. int whichField, whichComponent;
  4452. /*Returns a count of whichField's component dimensions*/
  4453. {
  4454.     return curFields[whichField] . components[whichComponent] . nIndices;
  4455. }
  4456.  
  4457. long *GetComponentDims(whichField, whichComponent)
  4458. int whichField, whichComponent;
  4459. /*Returns a count of whichField's component dimensions*/
  4460. {
  4461.     return curFields[whichField] . components[whichComponent] . dimensions;
  4462. }
  4463.  
  4464. #ifdef PROTO
  4465. Bool CompareReals(real *r1, real *r2, long nReals)
  4466. #else
  4467. Bool CompareReals(r1, r2, lnReals)
  4468. real *r1;
  4469. real *r2;
  4470. long nReals;
  4471. #endif
  4472. /*Compares a bunch of reals, with any luck fast.  Uses indices, not pointers,
  4473.   to take advantage of MIPS architecture*/
  4474. {
  4475.     register long k, max;
  4476.     register real *rc1, *rc2;
  4477.  
  4478.     rc1 = r1;
  4479.     rc2 = r2;
  4480.     max = nReals;
  4481.  
  4482.     for (k = 0; k < max; ++k)
  4483.     {
  4484.     if (rc1[k] != rc2[k]) return false;
  4485.     }
  4486.     return true;
  4487. }
  4488.  
  4489. #ifdef PROTO
  4490. Bool IdenticalFields(int field1, int field2)
  4491. #else
  4492. Bool IdenticalFields(field1, field2)
  4493. int field1, field2;
  4494. #endif
  4495. /*Returns true if the two fields are identical.  Tries to be quick about it.
  4496.   May return false falsely.
  4497. */
  4498. {
  4499.     register int k;
  4500.  
  4501.     if (curFields[field1] . topDim !=
  4502.     curFields[field2] . topDim) return false;
  4503.     if (curFields[field1] . nComponents !=
  4504.     curFields[field2] . nComponents) return false;
  4505.  
  4506.     /*Compare gross quantities*/
  4507.     if (curFields[field1] . fieldObj == curFields[field2] . fieldObj)
  4508.     {
  4509.     return true;
  4510.     }
  4511.  
  4512.     for (k = 0; k < curFields[field1] . nComponents; ++k)
  4513.     {
  4514.     register Component *comp1, *comp2;
  4515.     register int i;
  4516.  
  4517.     comp1 = &(curFields[field1] . components[k]);
  4518.     comp2 = &(curFields[field2] . components[k]);
  4519.  
  4520.     if (comp1 -> dataSize != comp2 -> dataSize) return false;
  4521.     if (comp1 -> dataCompressed || comp2 -> dataCompressed)
  4522.     {
  4523.         fprintf(stderr, "WARNING!  Can't do IdenticalFields on compressed grids\n");
  4524.         return false;
  4525.     }
  4526.     else if (!CompareReals(comp1 -> data . unComp, comp2 -> data . unComp, comp1 -> dataSize))
  4527.     {
  4528.         return false;
  4529.     }
  4530.     }
  4531.  
  4532.     /*Have to assume they're identical*/
  4533.     return true;
  4534. }
  4535.  
  4536. #ifdef PROTO
  4537. int CountTraversalDims(int whichField)
  4538. #else
  4539. int CountTraversalDims(whichField)
  4540. int whichField;
  4541. #endif
  4542. /*Counts the traversal dimensions in whichField*/
  4543. {
  4544.     int k, curIndex;
  4545.     int maxDim = 0, temp;
  4546.  
  4547.     for (k = 0; k < curFields[whichField] . nComponents; ++k)
  4548.     {
  4549.     temp = MaxComponentIndices(whichField, k);
  4550.     if (temp > maxDim) maxDim = temp;
  4551.     }
  4552.     return maxDim;
  4553. }
  4554.  
  4555. #ifdef PROTO
  4556. void GetTraversalDims(int whichField, long dims[])
  4557. #else
  4558. void GetTraversalDims(whichField, dims)
  4559. int whichField;
  4560. long dims[];
  4561. #endif
  4562. /*Gets the traversal dims in whichField into dims, which had better be big enough*/
  4563. {
  4564.     int whichComponent, whichIndex, index, indIndex;
  4565.     int nIndices;
  4566.  
  4567.     nIndices = CountTraversalDims(whichField);
  4568.  
  4569.     for (indIndex = 0; indIndex < nIndices; ++indIndex)
  4570.     {
  4571.     dims[indIndex] = -1;
  4572.     }
  4573.  
  4574.     for (whichComponent = 0; whichComponent < curFields[whichField] . nComponents; ++whichComponent)
  4575.     {
  4576.     for (whichIndex = 0; whichIndex < curFields[whichField] . components[whichComponent] . nIndices; ++whichIndex)
  4577.     {
  4578.         indIndex = curFields[whichField] . components[whichComponent] . indices[whichIndex];
  4579.         if (indIndex >= 0)
  4580.         {
  4581.         dims[indIndex] = curFields[whichField] . components[whichComponent] . dimensions[whichIndex];
  4582.         }
  4583.     }
  4584.     }
  4585. }
  4586.  
  4587. static ObjPtr RegisterDataFormField(form, whichField)
  4588. ObjPtr form;
  4589. int whichField;
  4590. /*Registers data form form in field whichField*/
  4591. {
  4592.     ObjPtr dataset;            /*Dataset that may define this dataform*/
  4593.  
  4594.     MakeVar(form, DATA);
  4595.     dataset = GetVar(form, DATA);
  4596.     if (dataset)
  4597.     {
  4598.     Bool test;
  4599.     ObjPtr var;
  4600.     /*It's based on a dataset*/
  4601.  
  4602.     test = SetCurField(whichField, dataset);
  4603.     curFields[whichField] . topDim = GetTopDim(form);
  4604.     return test ? ObjTrue : ObjFalse;
  4605.     }
  4606.  
  4607.     if (GetPredicate(form, UNSTRUCTURED))
  4608.     {
  4609.     /*Unstructured grid.  This is an error, as all unstructured grids
  4610.       must have a dataset in their form*/
  4611.     ReportError("RegisterDataFormField", "Unstructured grid without data");
  4612.     }
  4613.     else
  4614.     {
  4615.     ObjPtr dimsArray, boundsArray;
  4616.     real *dimsPtr, *boundsPtr;
  4617.     Component *components;
  4618.     int whichComponent;
  4619.     long topDim;
  4620.     long dataSize;
  4621.     Bool omErr = false;        /*True if om error occurred*/
  4622.  
  4623.     dimsArray = GetArrayVar("RegisterDataFormField", form, DIMENSIONS);
  4624.     boundsArray = GetArrayVar("RegisterDataFormField", form, BOUNDS);
  4625.     if (!dimsArray || !boundsArray)
  4626.     {
  4627.         return ObjFalse;
  4628.     }
  4629.  
  4630.     topDim = DIMS(dimsArray)[0];
  4631.  
  4632.     /*Topological dimension is now topDim  Create that many components*/
  4633.     components = (Component *) Alloc(sizeof(Component) * topDim);
  4634.  
  4635.     dimsPtr = ELEMENTS(dimsArray);
  4636.     boundsPtr = ELEMENTS(boundsArray);
  4637.  
  4638.     for (whichComponent = 0; whichComponent < topDim; ++whichComponent)
  4639.     {
  4640.         int *indices = 0;
  4641.         long *dimensions = 0;
  4642.         long *steps = 0;
  4643.         ObjPtr dataArray;
  4644.  
  4645.         /*Set up one index, the current component*/
  4646.         components[whichComponent] . nIndices = 1;
  4647.         indices = Alloc(sizeof(int));
  4648.         if (indices)
  4649.         {
  4650.         *indices = whichComponent;
  4651.         }
  4652.         else
  4653.         {
  4654.         omErr = true;
  4655.         OMErr();
  4656.         }
  4657.  
  4658.         /*One set of dimensions*/
  4659.         dimensions = Alloc(sizeof(int));
  4660.         if (dimensions)
  4661.         {
  4662.         *dimensions = *dimsPtr;
  4663.         }
  4664.         else
  4665.         {
  4666.         omErr = true;
  4667.         OMErr();
  4668.         }
  4669.  
  4670.         /*One step, unity*/
  4671.         steps = Alloc(sizeof(int));
  4672.         if (steps)
  4673.         {
  4674.         *steps = 1;
  4675.         }
  4676.         else
  4677.         {
  4678.         omErr = true;
  4679.         OMErr();
  4680.         }
  4681.  
  4682.         /*Fill in a data array*/
  4683.         dataArray = NewRealArray(1, (long) *dimsPtr);
  4684.         if (dataArray)
  4685.         {
  4686.         real min, max, *dp;
  4687.         long k;
  4688.         dp = ELEMENTS(dataArray);
  4689.         min = *boundsPtr;
  4690.         max = *(boundsPtr + 1);
  4691.  
  4692.         if (*dimsPtr < 1.5)
  4693.         {
  4694.             *dp = (min + max) * 0.5;
  4695.         }
  4696.         else for (k = 0; k < (long) *dimsPtr; ++k)
  4697.         {
  4698.             *dp = min + (max - min) * (k / (*dimsPtr - 1));
  4699.             ++dp;
  4700.         }
  4701.         }
  4702.         else
  4703.         {
  4704.         omErr = true;
  4705.         OMErr();
  4706.         }
  4707.         components[whichComponent] . flags = 0;
  4708.         components[whichComponent] . data . unComp = ELEMENTS(dataArray);
  4709.         components[whichComponent] . dataCompressed = false;
  4710.         components[whichComponent] . dataSize = (long) *dimsPtr;
  4711.         components[whichComponent] . indices = indices;
  4712.         components[whichComponent] . dimensions = dimensions;
  4713.         components[whichComponent] . steps = steps;
  4714.  
  4715.         ++dimsPtr;
  4716.         boundsPtr += 2;
  4717.     }
  4718.     curFields[whichField] . components = components;
  4719.     curFields[whichField] . nComponents = topDim;
  4720.     }
  4721.     return ObjTrue;
  4722. }
  4723.  
  4724. static ObjPtr DeleteDatasetIcon(icon)
  4725. ObjPtr icon;
  4726. /*Delete repObj from dataset icon within a corral.  Always OK.*/
  4727. {
  4728.     ObjPtr dataset;
  4729.  
  4730.     return ObjTrue;
  4731. }
  4732.  
  4733. static ObjPtr CleanupDataset(object)
  4734. ObjPtr object;
  4735. /*Cleans up a dataset*/
  4736. {
  4737.     /*Delete the object from the database*/
  4738.     DeleteObjFromDatabase(object);
  4739.  
  4740.     return ObjTrue;
  4741. }
  4742.  
  4743. static ObjPtr MakeDatasetIconHelp(object, class)
  4744. ObjPtr object;
  4745. ObjPtr class;
  4746. /*Makes a dataset icon help string*/
  4747. {
  4748.     long info;
  4749.     long topDim;
  4750.     ObjPtr repObj;
  4751.     char *s;
  4752.  
  4753.     repObj = GetVar(object, REPOBJ);
  4754.     if (!repObj)
  4755.     {
  4756.     SetVar(class, HELPSTRING,
  4757.        NewString("This icon is supposed to represent a dataset.  Unfortunately, \
  4758. it does not appear to be connected to anything right now.  See the section on Reporting Bugs \
  4759. to find out how to report this bug."));
  4760.     return ObjTrue;
  4761.     }
  4762.     info = GetDatasetInfo(repObj);
  4763.     if (info & DS_HASFORM)
  4764.     {
  4765.     topDim = GetTopDim(repObj);
  4766.     }
  4767.     else
  4768.     {
  4769.     topDim = 0;
  4770.     }
  4771.     s = tempStr;
  4772.     sprintf(s,
  4773.     "This icon represents a dataset, which contains");
  4774.     while (*s) ++s;
  4775.     if (info & (DS_HASGEOMETRY | DS_HASNEWGEOMETRY))
  4776.     {
  4777.     sprintf(s, "%s geometry.  ",
  4778.         info & DS_TIMEDEPENDENT ? " time-dependent" : "");
  4779.     }
  4780.     else
  4781.     {
  4782.     if (topDim)
  4783.     {
  4784.         sprintf(s, " a %d-D%s %s field.  ",
  4785.         topDim,
  4786.         info & DS_TIMEDEPENDENT ? " time-dependent" : "",
  4787.         info & DS_VECTOR ? "vector" : "scalar");
  4788.      }
  4789.     else
  4790.     {
  4791.         sprintf(s, " a%s %s field.  ",
  4792.         info & DS_TIMEDEPENDENT ? " time-dependent" : "",
  4793.         info & DS_VECTOR ? "vector" : "scalar");
  4794.     }
  4795.     }
  4796.     while (*s) ++s;
  4797.     strcpy(s, "You can select it and use the controls \
  4798. in this window to modify or visualize it, or you can drag it into the \
  4799. corral of an existing visualization window to visualize it there.");
  4800.  
  4801.     SetVar(class, HELPSTRING, NewString(tempStr));
  4802.     return ObjTrue;
  4803. }
  4804.  
  4805. ObjPtr DatasetPaletteSet(dataset)
  4806. ObjPtr dataset;
  4807. /*Sets PALETTESET on dataset*/
  4808. {
  4809.     SetVar(dataset, PALETTESET, ObjTrue);
  4810.     return ObjTrue;
  4811. }
  4812.  
  4813. static ObjPtr VisualizeDataset(object)
  4814. ObjPtr object;
  4815. /*Visualizes a single dataset in the current window*/
  4816. {
  4817.     if (object)
  4818.     {
  4819.     IdleAllWindows();
  4820.     AddObjToSpace(object, FindSpace(selWinInfo), GetVar((ObjPtr) selWinInfo, CORRAL), NULLOBJ, NULLOBJ);
  4821.     return ObjTrue;
  4822.     }
  4823.     return ObjFalse;
  4824. }
  4825.  
  4826. ObjPtr VisualizeDatasetAs(object)
  4827. ObjPtr object;
  4828. /*Visualizes an object as...*/
  4829. {
  4830.     AddToVisualizeAsList(object);
  4831.     return ObjTrue;
  4832. }
  4833.  
  4834. ObjPtr MakeDatasetControlIcon(dataset)
  4835. ObjPtr dataset;
  4836. /*Makes a dataset's control icon*/
  4837. {
  4838.     SetVar(dataset, CONTROLICON, GetVar(dataset, DEFAULTICON));
  4839.     return ObjTrue;
  4840. }
  4841.  
  4842. static ObjPtr MakeDatasetTimeBounds(dataset)
  4843. ObjPtr dataset;
  4844. /*Makes a dataset's time bounds*/
  4845. {
  4846.     ObjPtr var;
  4847.  
  4848.     var = GetVar(dataset, DATA);
  4849.     if (var)
  4850.     {
  4851.     MakeVar(var, TIMEBOUNDS);
  4852.     SetVar(dataset, TIMEBOUNDS, GetVar(var, TIMEBOUNDS));
  4853.     return ObjTrue;
  4854.     }
  4855.     var = GetVar(dataset, MAINDATASET);
  4856.     if (var)
  4857.     {
  4858.     MakeVar(var, TIMEBOUNDS);
  4859.     SetVar(dataset, TIMEBOUNDS, GetVar(var, TIMEBOUNDS));
  4860.     return ObjTrue;
  4861.     }
  4862.     return ObjFalse;
  4863. }
  4864.  
  4865. static ObjPtr MakeDatasetInterpolateP(dataset)
  4866. ObjPtr dataset;
  4867. /*Makes a dataset's INTERPOLATEP*/
  4868. {
  4869.     ObjPtr data;
  4870.  
  4871. #if 0
  4872.     MakeVar(dataset, DATA);
  4873.     data = GetVar(dataset, DATA);
  4874.     if (data)
  4875.     {
  4876.     CopyVar(dataset, data, INTERPOLATEP);
  4877.     return ObjTrue;
  4878.     }
  4879. #endif
  4880.  
  4881.     MakeVar(dataset, MAINDATASET);
  4882.     data = GetVar(dataset, MAINDATASET);
  4883.     if (data)
  4884.     {
  4885.     CopyVar(dataset, data, INTERPOLATEP);
  4886.     return ObjTrue;
  4887.     }
  4888.  
  4889.     SetVar(dataset, INTERPOLATEP, ObjTrue);
  4890.     return ObjTrue;
  4891. }
  4892.  
  4893. static ObjPtr MakeDataFormInterpolateP(dataset)
  4894. ObjPtr dataset;
  4895. /*Makes a data form's INTERPOLATEP*/
  4896. {
  4897.     ObjPtr data;
  4898.  
  4899.     MakeVar(dataset, DATA);
  4900.     data = GetVar(dataset, DATA);
  4901.     if (data)
  4902.     {
  4903.     CopyVar(dataset, data, INTERPOLATEP);
  4904.     return ObjTrue;
  4905.     }
  4906.  
  4907. #if 0
  4908.     MakeVar(dataset, MAINDATASET);
  4909.     data = GetVar(dataset, MAINDATASET);
  4910.     if (data)
  4911.     {
  4912.     CopyVar(dataset, data, INTERPOLATEP);
  4913.     return ObjTrue;
  4914.     }
  4915. #endif
  4916.     SetVar(dataset, INTERPOLATEP, ObjTrue);
  4917.     return ObjTrue;
  4918. }
  4919.  
  4920. static ObjPtr EditDatasetPalette(dataset)
  4921. ObjPtr dataset;
  4922. /*Edits a dataset's palette*/
  4923. {
  4924.     ObjPtr palette;
  4925.     MakeVar(dataset, CPALETTE);
  4926.     palette = GetPaletteVar("EditDatasetPalette", dataset, CPALETTE);
  4927.     if (palette)
  4928.     {
  4929.     NewControlWindow(palette);
  4930.     }
  4931.     return ObjTrue;
  4932. }
  4933.  
  4934. static ObjPtr MakeDataFormChanged(form)
  4935. ObjPtr form;
  4936. /*Makes a dataform changed*/
  4937. {
  4938.     SetVar(form, CHANGED, ObjTrue);
  4939.     return ObjTrue;
  4940. }
  4941.  
  4942. #ifdef PROTO
  4943. Bool DatabaseConflict(char *name, int classID)
  4944. #else
  4945. Bool DatabaseConflict(name, classID)
  4946. char *oldName;
  4947. int classID;
  4948. #endif
  4949. /*Returns true iff name and classID conflict with an object already in the database*/
  4950. {
  4951.     ObjPtr keyList, result;
  4952.  
  4953.     keyList = NewList();
  4954.     PostfixList(keyList, NewSymbol(NAME));
  4955.     PostfixList(keyList, NewString(name));
  4956.     PostfixList(keyList, NewSymbol(CLASSID));
  4957.     PostfixList(keyList, NewInt(classID));
  4958.  
  4959.     result = SearchDatabase(keyList);
  4960.     return (result && LISTOF(result)) ? true : false;
  4961. }
  4962.  
  4963. static ObjPtr DuplicateDataset(dataset)
  4964. ObjPtr dataset;
  4965. /*Duplicates a dataset*/
  4966. {
  4967.     ObjPtr icon;
  4968.  
  4969.     icon = ObjectWhichRepresents(selWinInfo, dataset);
  4970.     if (icon)
  4971.     {
  4972.     ObjPtr corral, newDataset;
  4973.     ObjPtr defaultIcon;
  4974.     ObjPtr var;
  4975.     char *name;
  4976.     ObjPtr palette;
  4977.  
  4978.     corral = GetVar(icon, PARENT);
  4979.  
  4980.     while (corral && !IsCorral(corral))
  4981.     {
  4982.         corral = GetVar(corral, PARENT);
  4983.     }
  4984.  
  4985.     if (!corral)
  4986.     {
  4987.         ReportError("DuplicateDataset", "Cannot find local corral");
  4988.         return ObjFalse;
  4989.     }
  4990.  
  4991.     newDataset = Clone(dataset);
  4992.  
  4993.     SetVar(newDataset, SELECTED, ObjFalse);
  4994.  
  4995.     MakeVar(newDataset, CPALETTE);
  4996.     palette = GetVar(newDataset, CPALETTE);
  4997.     SetVar(newDataset, CPALETTE, Clone(palette));
  4998.  
  4999.     /*Get the name*/
  5000.     MakeVar(newDataset, NAME);
  5001.     var = GetStringVar("DuplicateDataset", newDataset, NAME);
  5002.     if (!var)
  5003.     {
  5004.         return ObjFalse;
  5005.     }
  5006.     name = GetString(var);
  5007.  
  5008.     var = NewUniqueName(name, CLASS_DATASET);
  5009.     SetVar(newDataset, NAME, var);
  5010.     name = GetString(var);
  5011.     AddVolObjToDatabase(newDataset);
  5012.  
  5013.     /*Must create a new icon*/
  5014.     defaultIcon = GetVar(newDataset, DEFAULTICON);
  5015.     if (defaultIcon)
  5016.     {
  5017.         icon = NewObject(defaultIcon, 0);
  5018.         SetVar(icon, NAME, NewString(name));
  5019.     }
  5020.     else
  5021.     {
  5022.         icon = NewIcon(0, 0, ICONQUESTION, name);
  5023.         SetVar(icon, HELPSTRING,
  5024.         NewString("This icon represents a dataset.  You can select it and use the controls \
  5025. in this window to modify or visualize it, or you can drag it into the \
  5026. corral of an existing visualization window to visualize it there."));
  5027.     }
  5028.     SetVar(icon, REPOBJ, newDataset);
  5029.     SetVar(icon, CORRAL, corral);
  5030.     SetVar(icon, ICONLOC, NULLOBJ);
  5031.     DropIconInCorral(corral, icon);
  5032.      }
  5033.  
  5034.     return ObjTrue;
  5035. }
  5036.  
  5037. static ObjPtr RenameDataset(dataset, newName)
  5038. ObjPtr dataset;
  5039. ObjPtr newName;
  5040. /*Renames a dataset*/
  5041. {
  5042.     DeleteObjFromDatabase(dataset);
  5043.     SetVar(dataset, NAME, newName);
  5044.     AddObjToDatabase(dataset);
  5045.     return ObjTrue;
  5046. }
  5047.  
  5048. void InitDatasets()
  5049. /*Initializes all the kinds of data sets*/
  5050. {
  5051.     int k;
  5052.     for (k = 0; k < MAXNCURFIELDS * 2; ++k)
  5053.     {
  5054.     curFields[k] . nComponents = 0;
  5055.     curFields[k] . components = (Component *) 0;
  5056.     }
  5057.  
  5058.     iconDataset = NewIcon(0, 0, ICONQUESTION, "Dataset");
  5059.     AddToReferenceList(iconDataset);
  5060.     SetMethod(iconDataset, MAKE1HELPSTRING, MakeDatasetIconHelp);
  5061.     SetMethod(iconDataset, DELETEICON, DeleteDatasetIcon);
  5062.  
  5063.     icon4DScalar = NewObject(iconDataset, 0);
  5064.     SetVar(icon4DScalar, WHICHICON, NewInt(ICON4DSCALAR));
  5065.     AddToReferenceList(icon4DScalar);
  5066.  
  5067.     icon3DScalar = NewObject(iconDataset, 0);
  5068.     SetVar(icon3DScalar, WHICHICON, NewInt(ICON3DSCALAR));
  5069.     AddToReferenceList(icon3DScalar);
  5070.  
  5071.     icon2DScalar = NewObject(iconDataset, 0);
  5072.     SetVar(icon2DScalar, WHICHICON, NewInt(ICON2DSCALAR));
  5073.     AddToReferenceList(icon2DScalar);
  5074.  
  5075.     icon1DScalar = NewObject(iconDataset, 0);
  5076.     SetVar(icon1DScalar, WHICHICON, NewInt(ICON1DSCALAR));
  5077.     AddToReferenceList(icon1DScalar);
  5078.  
  5079.  
  5080.     icon4DVector = NewObject(iconDataset, 0);
  5081.     SetVar(icon4DVector, WHICHICON, NewInt(ICON4DVECTOR));
  5082.     AddToReferenceList(icon4DVector);
  5083.  
  5084.     icon3DVector = NewObject(iconDataset, 0);
  5085.     SetVar(icon3DVector, WHICHICON, NewInt(ICON3DVECTOR));
  5086.     AddToReferenceList(icon3DVector);
  5087.  
  5088.     icon2DVector = NewObject(iconDataset, 0);
  5089.     SetVar(icon2DVector, WHICHICON, NewInt(ICON2DVECTOR));
  5090.     AddToReferenceList(icon2DVector);
  5091.  
  5092.     icon1DVector = NewObject(iconDataset, 0);
  5093.     SetVar(icon1DVector, WHICHICON, NewInt(ICONVECTORS));
  5094.     AddToReferenceList(icon1DVector);
  5095.  
  5096.     datasetClass = NewObject(advertiseableClass, 0);
  5097.     AddToReferenceList(datasetClass);
  5098.     DeclareDependency(datasetClass, CHANGED, INTERPOLATEP);
  5099.     DeclareDependency(datasetClass, CHANGED, DATA);
  5100.     SetMethod(datasetClass, IMINVALID, DatasetInvalid);
  5101.     SetVar(datasetClass, CLASSID, NewInt(CLASS_DATASET));
  5102.     SetMethod(datasetClass, GETLONGNAME, GetPlainDatasetLongName);
  5103.     SetVar(datasetClass, DEFAULTICON, iconDataset);
  5104.     SetVar(datasetClass, NAME, NewString("Dataset"));
  5105.     SetVar(datasetClass, DOUBLECLICK, NewString(OF_SHOW_CONTROLS));
  5106.     DeclareIndirectDependency(datasetClass, TIMEBOUNDS, DATA, TIMEBOUNDS);
  5107.     DeclareIndirectDependency(datasetClass, TIMEBOUNDS, MAINDATASET, TIMEBOUNDS);
  5108.     SetMethod(datasetClass, TIMEBOUNDS, MakeDatasetTimeBounds);
  5109.     SetMethod(datasetClass, EDITPALETTE, EditDatasetPalette);
  5110.     SetMethod(datasetClass, CLEANUP, CleanupDataset);
  5111.     SetMethod(datasetClass, GETDATASETINFO, GetPlainDatasetInfo);
  5112.     SetMethod(datasetClass, MINMAX, GetDataMinMax);
  5113.     SetMethod(datasetClass, NEWCTLWINDOW, ShowDatasetControls);
  5114.     SetMethod(datasetClass, SHOWCONTROLS, NewControlWindow);
  5115.     SetMethod(datasetClass, REGISTERFIELD, RegisterDatasetField);
  5116.     SetMethod(datasetClass, REGISTERFORM, RegisterDatasetForm);
  5117.     SetMethod(datasetClass, GETTOPDIM, GetDatasetTopDim);
  5118.     SetMethod(datasetClass, GETSPATIALDIM, GetDatasetSpatialDim);
  5119.     SetMethod(datasetClass, GETFORMDIMS, GetPlainDatasetFormDims);
  5120.     SetMethod(datasetClass, DELETE, DeleteObject);
  5121.     SetMethod(datasetClass, ADDCONTROLS, AddDatasetControls);
  5122.     SetMethod(datasetClass, CONTROLICON, MakeDatasetControlIcon);
  5123.     DeclareIndirectDependency(datasetClass, INTERPOLATEP, MAINDATASET, INTERPOLATEP);
  5124.     SetMethod(datasetClass, INTERPOLATEP, MakeDatasetInterpolateP);
  5125.     DeclareIndirectDependency(datasetClass, PALETTESET, CPALETTE, CHANGED);
  5126.     DeclareIndirectDependency(datasetClass, PALETTESET, CPALETTE, JUSTCOLORCHANGE);
  5127.     SetMethod(datasetClass, CPALETTE, MakeDatasetPalette);
  5128.     SetMethod(datasetClass, PALETTESET, DatasetPaletteSet);
  5129.     DeclareDependency(datasetClass, TIMESTEPS, DATA);
  5130.     DeclareIndirectDependency(datasetClass, TIMESTEPS, DATA, TIMESTEPS);
  5131.     SetMethod(datasetClass, TIMESTEPS, MakeDatasetTimesteps);
  5132.     DeclareIndirectDependency(datasetClass, CHANGED, DATAFORM, CHANGED);
  5133.     SetMethod(datasetClass, VISUALIZE, VisualizeDataset);
  5134.     SetMethod(datasetClass, VISUALIZEAS, VisualizeDatasetAs);
  5135.     SetVar(datasetClass, INTERPOLATEP, ObjFalse);
  5136.     SetMethod(datasetClass, DUPLICATE, DuplicateDataset);
  5137.     SetMethod(datasetClass, RENAME, RenameDataset);
  5138.     SetVar(datasetClass, TYPESTRING, NewString("dataset"));
  5139.  
  5140.     dataFormClass = NewObject(NULLOBJ, 0);
  5141.     AddToReferenceList(dataFormClass);
  5142.     SetVar(dataFormClass, NCOMPONENTS, NewInt(3));
  5143.     SetMethod(dataFormClass, REGISTERFIELD, RegisterDataFormField);
  5144.     SetMethod(dataFormClass, GETTOPDIM, GetDataFormTopDim);
  5145.     DeclareIndirectDependency(dataFormClass, CHANGED, DATA, CHANGED);
  5146.     SetMethod(dataFormClass, INTERPOLATEP, MakeDataFormInterpolateP);
  5147.     DeclareIndirectDependency(dataFormClass, INTERPOLATEP, DATA, INTERPOLATEP);
  5148.     SetVar(dataFormClass, INTERPOLATEP, ObjTrue);
  5149.  
  5150.     data3DScalar = NewObject(datasetClass, 0);
  5151.     SetVar(data3DScalar, DEFAULTICON, icon3DScalar);
  5152.     AddToReferenceList(data3DScalar);
  5153.  
  5154.     data2DScalar = NewObject(datasetClass, 0);
  5155.     SetVar(data2DScalar, DEFAULTICON, icon2DScalar);
  5156.     AddToReferenceList(data2DScalar);
  5157.  
  5158.     data1DVector = NewObject(datasetClass, 0);
  5159.     SetVar(data1DVector, DEFAULTICON, icon1DVector);
  5160.     AddToReferenceList(data1DVector);
  5161.  
  5162.     data3DUnstructSurface = NewObject(datasetClass, 0);
  5163.     SetVar(data3DUnstructSurface, DEFAULTICON, icon2DScalar);
  5164.     AddToReferenceList(data3DUnstructSurface);
  5165.  
  5166.     /*Class for a geometry file*/
  5167.     iconGeometry = NewIcon(0, 0, ICONGEOMETRY, "Geometry");
  5168.     SetMethod(iconGeometry, DELETEICON, DeleteDatasetIcon);
  5169.     geometryClass = NewObject(datasetClass, 0);
  5170.     AddToReferenceList(geometryClass);
  5171.     SetVar(geometryClass, NAME, NewString("Geometry"));
  5172.     SetVar(geometryClass, DEFAULTICON, iconGeometry);
  5173.     SetMethod(geometryClass, DELETE, DeleteObject);
  5174. }
  5175.  
  5176. void KillDatasets()
  5177. /*Kills the data sets*/
  5178. {
  5179.     int k;
  5180.     for (k = 0; k < MAXNCURFIELDS * 2; ++k)
  5181.     {
  5182.     CleanCurField(k);
  5183.     }
  5184.     DeleteThing(geometryClass);
  5185.     DeleteThing(data3DUnstructSurface);
  5186.     DeleteThing(data1DVector);
  5187.     DeleteThing(data3DScalar);
  5188.     DeleteThing(data2DScalar);
  5189.     DeleteThing(dataFormClass);
  5190.     DeleteThing(datasetClass);
  5191.  
  5192.     DeleteThing(icon1DVector);
  5193.     DeleteThing(icon2DVector);
  5194.     DeleteThing(icon3DVector);
  5195.     DeleteThing(icon4DVector);
  5196.  
  5197.     DeleteThing(icon1DScalar);
  5198.     DeleteThing(icon2DScalar);
  5199.     DeleteThing(icon3DScalar);
  5200.     DeleteThing(icon4DScalar);
  5201.     DeleteThing(iconDataset);
  5202. }
  5203.